/* Shared design tokens and base components. Copy into every product with the fonts/ folder beside it, then override only what
   guides/foundations/identity.md allows (accent, product display face). What each value is for:
   guides/foundations/visual.md. The version is the guidelines' version, in CHANGELOG.md.
   Fonts: Archivo 400/500/700/800/900 + IBM Plex Mono 400, self-hosted in fonts/ so no third party is called.
   Weights have jobs: 400 to read, 500 to touch, 700 and up for titles. */

/* These paths are relative to this file, so keep fonts/ beside it. */
@font-face { font-family: "Archivo"; src: url(fonts/archivo.woff2) format("woff2"); font-weight: 400 900; font-display: swap; }
@font-face { font-family: "IBM Plex Mono"; src: url(fonts/ibm-plex-mono.woff2) format("woff2"); font-weight: 400; font-display: swap; }
/* System fonts stand in at the real fonts' width and height until those arrive, so text doesn't move. Values from scripts/mkfonts.py. */
@font-face { font-family: "Archivo Fallback"; src: local("Arial"), local("ArialMT"), local("Roboto"); font-weight: 400 500; size-adjust: 98.54%; ascent-override: 89.10%; descent-override: 21.31%; line-gap-override: 0%; }
@font-face { font-family: "Archivo Fallback"; src: local("Arial Bold"), local("Arial-BoldMT"), local("Roboto Bold"); font-weight: 600 700; size-adjust: 98.38%; ascent-override: 89.25%; descent-override: 21.35%; line-gap-override: 0%; }
@font-face { font-family: "Archivo Fallback"; src: local("Arial Bold"), local("Arial-BoldMT"), local("Roboto Bold"); font-weight: 800; size-adjust: 103.19%; ascent-override: 85.09%; descent-override: 20.35%; line-gap-override: 0%; }
@font-face { font-family: "Archivo Fallback"; src: local("Arial Bold"), local("Arial-BoldMT"), local("Roboto Bold"); font-weight: 900; size-adjust: 109.93%; ascent-override: 79.87%; descent-override: 19.10%; line-gap-override: 0%; }
@font-face { font-family: "IBM Plex Mono Fallback"; src: local("Menlo"), local("Courier New"), local("Droid Sans Mono"); font-weight: 400; size-adjust: 99.66%; ascent-override: 102.85%; descent-override: 27.59%; line-gap-override: 0%; }

:root {
  /* Color: black and white. Grey only for secondary text. */
  --pl-ink: #000000;
  --pl-paper: #FFFFFF;
  --pl-white: #FFFFFF;
  --pl-grey: #A1A1AA;        /* secondary text on ink ONLY (fails AA on paper) */
  --pl-grey-dark: #52525B;   /* secondary text on paper */
  --pl-rule: #E4E4E7;        /* hairlines on paper */
  --pl-rule-dark: #27272A;   /* hairlines on ink */
  --pl-signal: #D92D20;      /* errors and destructive actions only, never decoration */
  --pl-accent: var(--pl-ink); /* the fill: primary button, selection, progress. A product takes its shelf's accent from the palette below */
  --pl-on-accent: var(--pl-paper); /* text on the fill */
  --pl-accent-text: var(--pl-ink); /* the accent as text or a thin line: links, back, the current tab, focus rings */
  --pl-thumb: var(--pl-white); /* a switch's thumb: white on every accent. Ink only on the masterbrand in dark, where the track is white */
  /* Accent palette, one per shelf (Steve, 2026-11-06). x is the fill, x-on is the text on it, x-paper is x as text on white, x-ink is x as text and as an icon's full stop on black.
     Most can't be read as text on white, so there they stay black. Oxblood and Ultramarine are too dark for black, so they get a brighter value there. scripts/check.py tests all of these for AA.
     Which shelf has which: "accent" in scripts/products-full.json. */
  --pl-citrus: #C6FF00; --pl-citrus-on: #000000; --pl-citrus-paper: #000000; --pl-citrus-ink: #C6FF00;
  --pl-infrared: #FF3B3B; --pl-infrared-on: #000000; --pl-infrared-paper: #000000; --pl-infrared-ink: #FF3B3B;
  --pl-bronze: #B8875A; --pl-bronze-on: #000000; --pl-bronze-paper: #000000; --pl-bronze-ink: #B8875A;
  --pl-oxblood: #751C30; --pl-oxblood-on: #FFFFFF; --pl-oxblood-paper: #751C30; --pl-oxblood-ink: #D13D5E;
  --pl-ultramarine: #1729D4; --pl-ultramarine-on: #FFFFFF; --pl-ultramarine-paper: #1729D4; --pl-ultramarine-ink: #5866ED;
  --pl-sage: #A3B18A; --pl-sage-on: #000000; --pl-sage-paper: #000000; --pl-sage-ink: #A3B18A;

  /* Semantic roles (light) */
  --pl-bg: var(--pl-paper);
  --pl-surface: var(--pl-white);
  --pl-fg: var(--pl-ink);
  --pl-fg-muted: var(--pl-grey-dark);
  --pl-line: var(--pl-rule);
  --pl-scrim: color-mix(in srgb, var(--pl-ink) 32%, transparent);
  --pl-inverse-bg: var(--pl-ink);
  --pl-inverse-fg: var(--pl-paper);

  /* Type */
  --pl-font: "Archivo", "Archivo Fallback", "Helvetica Neue", Arial, sans-serif;
  --pl-font-display: var(--pl-font); /* a product may swap this inside its app */
  --pl-font-mono: "IBM Plex Mono", "IBM Plex Mono Fallback", ui-monospace, Menlo, monospace;
  --pl-text-xs: 12px;   /* mono labels, stamps. Nothing is smaller */
  --pl-text-sm: 14px;   /* secondary text, never for long reading */
  --pl-text-md: 17px;   /* body. 16px is the floor for anything long */
  --pl-text-lg: 20px;   /* lead, item titles */
  --pl-text-xl: 24px;   /* section heading */
  --pl-text-2xl: 32px;  /* minimum for wall and TV (3 m) */
  --pl-text-3xl: 44px;  /* screen title on a wide screen */
  --pl-text-4xl: 72px;  /* display, masterbrand pages */
  --pl-text-5xl: 104px; /* hero, masterbrand only */
  --pl-text-kids: 22px; /* minimum in children's products */
  --pl-tracking-display: -0.03em;
  --pl-tracking-mono: 0.04em;
  --pl-tracking-stamp: 0.04em;
  --pl-tracking-title: -0.025em;
  --pl-tracking-control: -0.011em;
  --pl-leading-tight: 1.05;
  --pl-leading-body: 1.55;

  /* Space: 4px base */
  --pl-1: 4px; --pl-2: 8px; --pl-3: 12px; --pl-4: 16px; --pl-5: 24px;
  --pl-6: 32px; --pl-7: 48px; --pl-8: 72px; --pl-9: 112px;

  /* Shape. Identity stays square: the mark, app icons and stamps. Anything you touch is soft, on the
     same scale as shadcn's. Desktop tightens it (data-platform below). */
  --pl-radius: 10px;
  --pl-radius-sm: calc(var(--pl-radius) * .6);      /* checkboxes, small marks */
  --pl-radius-control: calc(var(--pl-radius) * 1.4); /* buttons, fields, grouped lists, toasts */
  --pl-radius-xl: calc(var(--pl-radius) * 2);       /* sheets and dialogs */
  --pl-radius-full: 999px;                          /* switches, radios, chips, floating controls */
  --pl-hairline: 1px;
  --pl-rule-weight: 2px;   /* opens a section */
  --pl-stamp-weight: 1px;
  --pl-shadow-thumb: 0 1px 2px rgb(0 0 0 / .14), 0 0 0 .5px rgb(0 0 0 / .05);   /* the selected segment, the switch thumb */
  --pl-shadow: 0 6px 24px rgb(0 0 0 / .10), 0 0 0 .5px rgb(0 0 0 / .06); /* what floats: sheets, toasts, menus */
  /* Light comes from above (ST4). A raised thing has a lit top edge and a small shadow under it; a sunk thing has the shade at its top. */
  --pl-sheen: inset 0 .5px 0 rgb(255 255 255 / .34);  /* the lit top edge of anything filled */
  --pl-rest: 0 1px 2px rgb(0 0 0 / .06), 0 3px 10px -3px rgb(0 0 0 / .09); /* what rests on the page: a card, a picture, a filled button */
  --pl-well: inset 0 1px 2px rgb(0 0 0 / .09);  /* what's sunk into the page: a field, a switch track, a segmented control */
  --pl-glow: 0 0 0 transparent;  /* on black, an accent gives off light. A product with an accent sets this in dark (ST10) */
  --pl-grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .5 0 0 0 0 .5 0 0 0 0 .5 0 0 0 1 0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E"); /* surface grain, for .pl-grain */

  /* Motion */
  --pl-spring: cubic-bezier(.32, .72, 0, 1); /* sheets: fast off the mark, settles without a bounce */
  --pl-fast: 120ms;
  --pl-base: 200ms;
  --pl-ease: cubic-bezier(.2, 0, 0, 1);

  /* Layout */
  --pl-max: 1120px;
  --pl-measure: 54ch;      /* widest reading text: holds Archivo under 75 characters a line */
  --pl-gutter: 24px;       /* 16px under 480px */
  --pl-touch: 44px;        /* smallest tap target and default control height with a mouse; 48px on touch, below */
  --pl-touch-kids: 64px;   /* children's products */
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --pl-bg: var(--pl-ink); --pl-surface: #141414; --pl-fg: var(--pl-paper);
    --pl-fg-muted: var(--pl-grey); --pl-line: var(--pl-rule-dark);
    --pl-inverse-bg: var(--pl-paper); --pl-inverse-fg: var(--pl-ink);
    --pl-signal: #F97066; --pl-accent: var(--pl-paper); --pl-on-accent: var(--pl-ink); --pl-accent-text: var(--pl-paper); --pl-thumb: var(--pl-ink); color-scheme: dark;
    --pl-shadow-thumb: 0 1px 3px rgb(0 0 0 / .5); --pl-shadow: 0 8px 32px rgb(0 0 0 / .6);
    --pl-sheen: inset 0 .5px 0 rgb(255 255 255 / .22); --pl-rest: inset 0 .5px 0 rgb(255 255 255 / .09), 0 1px 2px rgb(0 0 0 / .5); --pl-well: inset 0 1px 2px rgb(0 0 0 / .5);
  }
}
:root[data-theme="dark"] {
  --pl-bg: var(--pl-ink); --pl-surface: #141414; --pl-fg: var(--pl-paper);
  --pl-fg-muted: var(--pl-grey); --pl-line: var(--pl-rule-dark);
  --pl-inverse-bg: var(--pl-paper); --pl-inverse-fg: var(--pl-ink);
  --pl-signal: #F97066; --pl-accent: var(--pl-paper); --pl-on-accent: var(--pl-ink); --pl-accent-text: var(--pl-paper); --pl-thumb: var(--pl-ink); color-scheme: dark;
    --pl-shadow-thumb: 0 1px 3px rgb(0 0 0 / .5); --pl-shadow: 0 8px 32px rgb(0 0 0 / .6);
    --pl-sheen: inset 0 .5px 0 rgb(255 255 255 / .22); --pl-rest: inset 0 .5px 0 rgb(255 255 255 / .09), 0 1px 2px rgb(0 0 0 / .5); --pl-well: inset 0 1px 2px rgb(0 0 0 / .5);
}

@media (max-width: 479px) { :root { --pl-gutter: 16px; } }
/* iPhone, iPad, Mac (guides/surfaces/devices.md). Respond to abilities, never the device's name.
   Breakpoints: one column under 768px; more room from 768px; capped at --pl-max. */
@media (pointer: coarse) { :root { --pl-touch: 48px; } }
:root {
  --pl-safe-t: env(safe-area-inset-top, 0px); --pl-safe-r: env(safe-area-inset-right, 0px);
  --pl-safe-b: env(safe-area-inset-bottom, 0px); --pl-safe-l: env(safe-area-inset-left, 0px);
}
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
input, select, textarea { font-size: max(16px, 1em); }   /* under 16px, Safari zooms on focus */
.pl-screen { min-height: 100dvh; }                       /* not 100vh: Safari's toolbars come and go */
.pl-page { width: 100%; max-width: var(--pl-max); margin-inline: auto;
  padding-inline: max(var(--pl-gutter), var(--pl-safe-l)) max(var(--pl-gutter), var(--pl-safe-r)); }
@media (prefers-reduced-motion: reduce) { :root { --pl-fast: 0ms; --pl-base: 0ms; } }

/* Platform: set <html data-platform="desktop|tablet"> per product, never by reading the device.
   Mobile first is the default, on iPhone's sizes: 17 pt text, 44 pt targets.
   iPad first keeps touch sizes with a little less height, because there's room around it.
   Desktop only uses shadcn's own density, close to a Mac: 14 px text and 32 px controls. */
:root {
  --pl-control: var(--pl-touch); --pl-control-lg: 52px; --pl-field: max(48px, var(--pl-touch));
  --pl-body: var(--pl-text-md); --pl-secondary: var(--pl-text-sm); --pl-row-y: 11px; --pl-icon: 20px;
  --pl-button-weight: 500; --pl-button-size: 16px; --pl-button-pad: 18px; --pl-chip: 32px; --pl-seg: 32px;
  --pl-title: 30px; --pl-heading: 22px; --pl-sw-w: 51px; --pl-sw-h: 31px; --pl-check: 22px;
}
@media (min-width: 768px) { :root { --pl-heading: 24px; } }
:root[data-platform="tablet"] { --pl-control-lg: 48px; --pl-field: var(--pl-touch); --pl-title: 28px; }
:root[data-platform="desktop"] {
  --pl-radius: 6px;
  --pl-control: 32px; --pl-control-lg: 36px; --pl-field: 32px;
  --pl-body: 14px; --pl-secondary: 13px; --pl-row-y: 6px; --pl-icon: 16px;
  --pl-button-size: 14px; --pl-button-pad: 16px; --pl-chip: 28px; --pl-seg: 28px; --pl-title: 20px; --pl-heading: 16px; --pl-sw-w: 32px; --pl-sw-h: 18px; --pl-check: 16px;
}

/* Fills and separators are the foreground at low opacity, so they flip with the theme.
   The edge of a field is the one line that has to reach 3:1. */
:root {
  --pl-fill: color-mix(in srgb, var(--pl-fg) 6%, transparent);
  --pl-fill-hover: color-mix(in srgb, var(--pl-fg) 10%, transparent);
  --pl-fill-selected: color-mix(in srgb, var(--pl-fg) 13%, transparent);
  --pl-fill-strong: color-mix(in srgb, var(--pl-fg) 16%, transparent);
  --pl-separator: color-mix(in srgb, var(--pl-fg) 12%, transparent);
  --pl-edge: color-mix(in srgb, var(--pl-fg) 45%, var(--pl-bg));
  --pl-segment: var(--pl-surface);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) { --pl-segment: color-mix(in srgb, var(--pl-fg) 22%, transparent); }
}
:root[data-theme="dark"] { --pl-segment: color-mix(in srgb, var(--pl-fg) 22%, transparent); }

/* Components for products with no framework, drawn to match the shared shadcn theme: Apple's HIG on
   sizes and behavior, shadcn's look. Soft shapes and fills, still 44 pt, AA and keyboard-ready. When to use each: guides/patterns/. What draws what: guides/build/components.md */
.pl-btn, .pl-chip, .pl-seg button, .pl-row, .pl-card--link { -webkit-tap-highlight-color: transparent; }
.pl-btn, .pl-input, .pl-chip, .pl-seg, .pl-seg button, .pl-row, .pl-card, .pl-group, .pl-toggle, .pl-toast, .pl-banner, .pl-empty, .pl-sheet, .pl-tabbar, .pl-action-bar { box-sizing: border-box; }

/* Buttons. Plain .pl-btn is Secondary: a soft fill, so the one Primary stands out by style, not size. */
.pl-btn { display: inline-flex; align-items: center; justify-content: center; gap: var(--pl-2);
  min-height: var(--pl-control); padding: 0 var(--pl-button-pad); font: var(--pl-button-weight) var(--pl-button-size)/1.1 var(--pl-font); letter-spacing: var(--pl-tracking-control);
  border: 0; border-radius: var(--pl-radius-control); background: var(--pl-fill); color: var(--pl-fg);
  cursor: pointer; text-decoration: none; user-select: none;
  transition: background-color var(--pl-fast) var(--pl-ease), color var(--pl-fast) var(--pl-ease), opacity var(--pl-fast) var(--pl-ease); }
@media (hover: hover) { .pl-btn:hover { background: var(--pl-fill-hover); } }
.pl-btn:active, .pl-chip:active, .pl-seg button:active, .pl-tile:active, .pl-item:active, .pl-back:active, .pl-tabbar a:active, .pl-toast button:active, .pl-toast a:active { opacity: .7; transition-duration: 0ms; } /* pressing dims, on every control */
.pl-btn--primary { background: var(--pl-fg); color: var(--pl-bg); box-shadow: var(--pl-sheen), var(--pl-rest); } /* ink, not the accent: the color is the light on the screen, and a button that size would be paint */
@media (hover: hover) { .pl-btn--primary:hover { background: color-mix(in srgb, var(--pl-fg) 88%, var(--pl-bg)); } }
.pl-btn--text { background: transparent; padding: 0 var(--pl-2); color: var(--pl-accent-text); }
@media (hover: hover) { .pl-btn--text:hover { background: transparent; text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; } }
.pl-btn--danger { background: transparent; color: var(--pl-signal); } /* red text, so it never competes with the Primary */
@media (hover: hover) { .pl-btn--danger:hover { background: color-mix(in srgb, var(--pl-signal) 10%, transparent); } }
.pl-btn--large { min-height: var(--pl-control-lg); width: 100%; padding: 0 var(--pl-5); }
@media (min-width: 768px) { .pl-btn--large { width: auto; min-width: 160px; } }
.pl-btn--compact { position: relative; min-height: 32px; padding: 0 var(--pl-3); font-size: var(--pl-text-sm); border-radius: var(--pl-radius-sm); }
.pl-btn--compact::after { content: ""; position: absolute; inset: -6px 0; } /* 32px to see, 44px to hit. Dense desktop tables only */
@media (pointer: coarse) { .pl-btn--compact { min-height: var(--pl-touch); } }
.pl-btn--icon { width: var(--pl-control); padding: 0; background: transparent; }
@media (hover: hover) { .pl-btn--icon:hover { background: var(--pl-fill); } }
.pl-btn svg { width: var(--pl-icon); height: var(--pl-icon); flex: none; }
.pl-btn:disabled, .pl-btn[aria-disabled="true"] { opacity: 1; background: var(--pl-fill); color: color-mix(in srgb, var(--pl-fg) 38%, transparent); cursor: not-allowed; } /* neutral: an unavailable button carries no brand color */
.pl-btn--text:disabled, .pl-btn--text[aria-disabled="true"], .pl-btn--danger:disabled, .pl-btn--danger[aria-disabled="true"] { background: transparent; }
.pl-btn[aria-busy="true"] { pointer-events: none; cursor: progress; }
.pl-btn[aria-busy="true"]::before { content: ""; width: 13px; height: 13px; border-radius: var(--pl-radius-full); border: 1.5px solid currentColor; border-right-color: transparent; animation: pl-spin .7s linear infinite; }
@keyframes pl-spin { to { transform: rotate(360deg); } }

/* The focus ring shows for keyboards only, in the product's accent. */
.pl-btn:focus-visible, .pl-input:focus-visible, .pl-chip:focus-visible, .pl-row:focus-visible, .pl-seg button:focus-visible,
.pl-switch:focus-visible, .pl-check:focus-visible, .pl-card--link:focus-visible, .pl-tabbar a:focus-visible, .pl-tile:focus-visible, .pl-item:focus-visible, .pl-back:focus-visible, .pl-mini:focus-visible,
.pl-toast button:focus-visible, .pl-toast a:focus-visible { outline: 2px solid var(--pl-accent-text); outline-offset: 2px; }

/* Fields. Sentence-case label in the body face: a form should read like a person asking. */
.pl-label { display: block; font: 500 var(--pl-secondary)/1.4 var(--pl-font); margin-bottom: 8px; color: var(--pl-fg-muted); }
.pl-input { display: block; min-height: var(--pl-field); width: 100%; padding: 10px var(--pl-4); font: 400 var(--pl-body)/1.35 var(--pl-font);
  border: var(--pl-hairline) solid var(--pl-edge); border-radius: var(--pl-radius-control); background: var(--pl-surface); color: var(--pl-fg);
  box-shadow: var(--pl-well); transition: border-color var(--pl-fast) var(--pl-ease); }
.pl-input::placeholder { color: var(--pl-fg-muted); }
.pl-input:focus-visible { outline-offset: -1px; }
.pl-input[aria-invalid="true"] { border: 1.5px solid var(--pl-signal); padding: 9.5px 15.5px; }
/* Disabled in three channels, so it reads without guessing. opacity:1 and the text-fill stop Safari dimming it again. */
.pl-input:disabled { background: var(--pl-fill); border-color: var(--pl-separator); color: var(--pl-fg-muted); -webkit-text-fill-color: var(--pl-fg-muted); cursor: not-allowed; opacity: 1; }
.pl-hint { display: block; margin-top: 6px; font-size: var(--pl-text-sm); line-height: 1.4; color: var(--pl-fg-muted); }
.pl-error { display: block; margin-top: 6px; font-size: var(--pl-text-sm); line-height: 1.4; color: var(--pl-signal); }
.pl-search { position: relative; display: block; }
.pl-search .pl-input { padding-left: 40px; }
.pl-search svg { position: absolute; left: 12px; top: 50%; width: 18px; height: 18px; translate: 0 -50%; color: var(--pl-fg-muted); pointer-events: none; }

/* Switch, applied at once: <label class="pl-toggle">Sound <input class="pl-switch" type="checkbox" role="switch"></label> */
.pl-toggle { display: flex; align-items: center; justify-content: space-between; gap: var(--pl-4); min-height: var(--pl-control); cursor: pointer; }
.pl-switch { appearance: none; -webkit-appearance: none; position: relative; flex: none; width: var(--pl-sw-w); height: var(--pl-sw-h); margin: 0; border-radius: var(--pl-radius-full);
  background: var(--pl-fill-strong); box-shadow: var(--pl-well); cursor: pointer; transition: background-color var(--pl-base) var(--pl-ease); }
.pl-switch::before { content: ""; position: absolute; top: 2px; left: 2px; width: calc(var(--pl-sw-h) - 4px); height: calc(var(--pl-sw-h) - 4px); border-radius: var(--pl-radius-full); background: var(--pl-white); box-shadow: var(--pl-shadow-thumb);
  transition: translate var(--pl-base) var(--pl-spring); }
.pl-switch:checked { background: var(--pl-accent); box-shadow: var(--pl-well), var(--pl-glow); }
.pl-switch:checked::before { translate: calc(var(--pl-sw-w) - var(--pl-sw-h)) 0; background: var(--pl-thumb); }
/* Disabled keeps showing on or off: the thumb stays where it is, in grey. */
.pl-switch:disabled { background: var(--pl-fill); cursor: not-allowed; }
.pl-switch:disabled::before { background: color-mix(in srgb, var(--pl-fg) 35%, var(--pl-bg)); box-shadow: none; }
.pl-switch:disabled:checked { background: color-mix(in srgb, var(--pl-fg) 35%, var(--pl-bg)); }
.pl-switch:disabled:checked::before { background: var(--pl-bg); }
.pl-toggle:has(.pl-switch:disabled) { color: var(--pl-fg-muted); cursor: not-allowed; }
/* Checkbox and radio: a round radio can't be mistaken for a checkbox. */
.pl-check { appearance: none; -webkit-appearance: none; display: inline-grid; place-content: center; flex: none; width: var(--pl-check); height: var(--pl-check); margin: 0; border: 1px solid var(--pl-edge); border-radius: var(--pl-radius-sm); background: var(--pl-surface); cursor: pointer;
  transition: background-color var(--pl-fast) var(--pl-ease), border-color var(--pl-fast) var(--pl-ease); }
.pl-check[type="radio"] { border-radius: var(--pl-radius-full); }
.pl-check:checked { background: var(--pl-accent); border-color: var(--pl-accent); }
.pl-check:checked::before { content: ""; width: 11px; height: 6px; margin-top: -3px; border: solid var(--pl-on-accent); border-width: 0 0 1.75px 1.75px; rotate: -45deg; }
.pl-check[type="radio"]:checked::before { width: 10px; height: 10px; margin: 0; border: 0; border-radius: var(--pl-radius-full); background: var(--pl-on-accent); rotate: 0deg; }
.pl-choice { display: flex; align-items: center; gap: var(--pl-3); min-height: var(--pl-control); cursor: pointer; }

/* A pill means you can tap it. 32 px to see; the rest of the target is transparent border, and the corners stay round. */
.pl-chip { --spare: calc((var(--pl-control) - var(--pl-chip)) / 2); display: inline-flex; align-items: center; gap: 6px; min-height: var(--pl-control); padding: 0 12px; font: 500 var(--pl-secondary)/1 var(--pl-font); letter-spacing: -0.006em;
  border: solid transparent; border-width: var(--spare) 0; border-radius: calc(var(--pl-chip) / 2) / calc(var(--pl-chip) / 2 + var(--spare)); background-color: var(--pl-fill); background-clip: padding-box; color: var(--pl-fg); cursor: pointer; white-space: nowrap; text-decoration: none;
  transition: background-color var(--pl-fast) var(--pl-ease), color var(--pl-fast) var(--pl-ease); }
@media (hover: hover) { .pl-chip:hover { background-color: var(--pl-fill-hover); } }
.pl-chip[aria-pressed="true"] { background-color: var(--pl-fill-selected); color: var(--pl-fg); }
.pl-chip[aria-pressed="true"]::before { content: ""; width: 9px; height: 5px; margin: -2px 1px 0 0; border: solid currentColor; border-width: 0 0 1.5px 1.5px; rotate: -45deg; } /* a check, so selection is never only a shade */
@media (hover: hover) { .pl-chip[aria-pressed="true"]:hover { background-color: var(--pl-fill-strong); } }
.pl-chip:focus-visible { outline-offset: calc(2px - var(--spare)); }

/* Segmented control: two to five options, all visible. <div class="pl-seg" role="group"><button aria-pressed="true">…</button>… */
.pl-seg { --spare: calc((var(--pl-control) - var(--pl-seg)) / 2); position: relative; isolation: isolate; display: flex; max-width: 100%; padding: 0 2px; }
.pl-seg::before { content: ""; position: absolute; z-index: -2; inset: calc(var(--spare) - 2px) 0; border-radius: var(--pl-radius); background: var(--pl-fill); box-shadow: var(--pl-well); } /* the track */
.pl-seg button { position: relative; flex: 1 1 0; min-height: var(--pl-control); padding: 0 12px; border: 0; border-radius: calc(var(--pl-radius) - 2px); background: transparent; color: var(--pl-fg); font: 500 var(--pl-secondary)/1 var(--pl-font); letter-spacing: -0.006em; cursor: pointer; white-space: nowrap; }
.pl-seg button::before { content: ""; position: absolute; z-index: -1; inset: var(--spare) 0; border-radius: inherit; transition: background-color var(--pl-fast) var(--pl-ease); } /* what you see of a segment; the button itself is the full target */
.pl-seg button[aria-pressed="true"]::before { background: var(--pl-segment); box-shadow: var(--pl-shadow-thumb); }
@media (hover: hover) { .pl-seg button:not([aria-pressed="true"]):hover::before { background: var(--pl-fill); } }
.pl-seg button:focus-visible { outline-offset: calc(0px - var(--spare)); }

/* Cards and grouped lists, like Settings on a phone. */
.pl-card { padding: var(--pl-4); border-radius: var(--pl-radius-control); box-shadow: 0 0 0 .5px var(--pl-separator), var(--pl-rest); background: var(--pl-surface); color: inherit; }
.pl-card--link { display: block; text-decoration: none; transition: background-color var(--pl-fast) var(--pl-ease); }
@media (hover: hover) { .pl-card--link:hover { background: var(--pl-fill); } }
.pl-card--link:active { background: var(--pl-fill-strong); }
.pl-group { border-radius: var(--pl-radius-control); box-shadow: 0 0 0 .5px var(--pl-separator), var(--pl-rest); background: var(--pl-surface); overflow: hidden; }
.pl-group__title { display: block; margin: 0 0 8px; font-size: var(--pl-secondary); font-weight: 500; color: var(--pl-fg-muted); }
@media (min-resolution: 2dppx) { .pl-group > * + *::before { height: .5px; } }
.pl-group .pl-row, .pl-group .pl-toggle { padding: var(--pl-row-y) var(--pl-4); min-height: var(--pl-control); border-bottom: 0; }
.pl-group > * + *::before { content: ""; position: absolute; top: 0; left: var(--pl-4); right: 0; height: 1px; background: var(--pl-separator); }
.pl-group > * + * { position: relative; }
.pl-row { display: grid; grid-template-columns: auto 1fr auto; gap: var(--pl-3); align-items: center; width: 100%; min-height: var(--pl-control);
  padding: var(--pl-row-y) var(--pl-2); border: 0; border-radius: var(--pl-radius); background: none; color: inherit; text-align: left; font: inherit; text-decoration: none; }
.pl-group .pl-row { border-radius: 0; }
.pl-row--ruled { border-bottom: var(--pl-hairline) solid var(--pl-separator); border-radius: 0; padding-inline: 0; }
.pl-row b { display: block; font-weight: 400; }
.pl-row small { display: block; font-size: var(--pl-text-sm); line-height: 1.35; color: var(--pl-fg-muted); }
.pl-row__no { font: 400 var(--pl-text-xs)/1.4 var(--pl-font-mono); font-variant-numeric: tabular-nums; color: var(--pl-fg-muted); }
.pl-row__go { color: var(--pl-fg-muted); font-size: var(--pl-text-lg); line-height: 1; }
a.pl-row, button.pl-row { cursor: pointer; transition: background-color var(--pl-fast) var(--pl-ease); }
a.pl-row:active, button.pl-row:active { background: var(--pl-fill-strong); }
@media (hover: hover) { a.pl-row:hover, button.pl-row:hover { background: var(--pl-fill); } }
/* A thing you can open: a picture in a fixed shape, then at most two lines each (LS3), never cut to one. Set --pl-item-ratio, and --pl-item-width in a rail.
   <a class="pl-item" href="…"><img src="…" alt=""><b>Asado de tira</b><small>45 min · Kamado</small></a> */
.pl-item { display: block; min-width: 0; color: inherit; text-decoration: none; -webkit-tap-highlight-color: transparent; }
.pl-item > img { display: block; width: 100%; aspect-ratio: var(--pl-item-ratio, 1); object-fit: cover; border-radius: var(--pl-radius-control); box-shadow: var(--pl-rest); }
.pl-item > b, .pl-item > small { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
.pl-item > b { margin-top: var(--pl-2); font-size: var(--pl-button-size); font-weight: 500; line-height: 1.25; letter-spacing: var(--pl-tracking-control); }
.pl-item > small { margin-top: 2px; font-size: var(--pl-secondary); line-height: 1.35; color: var(--pl-fg-muted); }
.pl-rail > .pl-item { width: var(--pl-item-width, 148px); }

/* Facts about a thing: a label and a short value, on hairlines rather than in boxes. Numbers take .pl-n; a sentence belongs in the text, not here.
   <dl class="pl-facts"><div><dt>Cook</dt><dd class="pl-n">1 h 15 min</dd></div>…</dl> */
.pl-facts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 var(--pl-4); margin: 0; }
.pl-facts > div { min-width: 0; padding: var(--pl-2) 0; border-top: var(--pl-hairline) solid var(--pl-separator); }
.pl-facts dt { font-size: var(--pl-secondary); line-height: 1.35; color: var(--pl-fg-muted); }
.pl-facts dd { margin: 2px 0 0; font-size: var(--pl-button-size); line-height: 1.3; }
.pl-n { font-family: var(--pl-font-mono); font-variant-numeric: tabular-nums; } /* a number, a date or a price (ST6) */
.pl-count { display: inline-grid; place-content: center; min-width: 20px; height: 20px; padding: 0 6px; border-radius: var(--pl-radius-full); background: var(--pl-fill); font: 400 var(--pl-text-xs)/1 var(--pl-font-mono); font-variant-numeric: tabular-nums; }

/* Feedback. */
.pl-toast { display: flex; align-items: center; gap: var(--pl-3); justify-content: space-between; min-height: 56px; padding: 6px 8px 6px var(--pl-4);
  border-radius: var(--pl-radius-control); background: var(--pl-surface); color: var(--pl-fg); font-size: var(--pl-secondary); box-shadow: 0 0 0 1px var(--pl-separator), var(--pl-shadow); }
.pl-toast button, .pl-toast a { min-height: var(--pl-control); padding: 0 var(--pl-2); border: 0; border-radius: var(--pl-radius); background: none; color: var(--pl-accent-text); font: 500 var(--pl-secondary)/1 var(--pl-font); text-decoration: none; cursor: pointer; }
.pl-banner { display: flex; gap: var(--pl-3); align-items: flex-start; padding: var(--pl-3) var(--pl-4); border-radius: var(--pl-radius-control); background: var(--pl-fill); color: var(--pl-fg-muted); font-size: var(--pl-text-sm); line-height: 1.45; text-wrap: pretty; }
.pl-banner b { display: block; color: var(--pl-fg); font-size: var(--pl-button-size); font-weight: 500; }
.pl-banner--error::before { content: "!"; flex: none; display: grid; place-items: center; width: 18px; height: 18px; margin-top: 2px; border-radius: var(--pl-radius-full); background: var(--pl-signal); color: var(--pl-bg); font: 700 var(--pl-text-xs)/1 var(--pl-font); } /* a small red mark, never a pink box */
.pl-empty { display: grid; gap: var(--pl-2); justify-items: center; width: 100%; padding: var(--pl-5) var(--pl-2); text-align: center; }
.pl-empty b { font-size: var(--pl-body); font-weight: 500; letter-spacing: var(--pl-tracking-control); }
.pl-empty > span:not(:has(.pl-btn)) { color: var(--pl-fg-muted); max-width: var(--pl-measure); }
.pl-skeleton { display: block; border-radius: var(--pl-radius-sm); background: var(--pl-fill); animation: pl-pulse 1.6s var(--pl-ease) infinite; }
@keyframes pl-pulse { 50% { opacity: .55; } }

/* Sheet: rises from the bottom on a phone, with a grabber; a centered dialog from 640px. Use <dialog class="pl-sheet">. */
.pl-sheet { width: 100%; max-width: none; max-height: 88dvh; margin: auto 0 0; padding: var(--pl-3) var(--pl-5) max(var(--pl-5), var(--pl-safe-b)); overflow: auto; border: 0;
  border-radius: var(--pl-radius-xl) var(--pl-radius-xl) 0 0; background: var(--pl-surface); color: var(--pl-fg); box-shadow: var(--pl-shadow); }
.pl-sheet::before { content: ""; display: block; width: 36px; height: 5px; margin: 0 auto var(--pl-3); border-radius: var(--pl-radius-full); background: var(--pl-fill-strong); }
.pl-sheet::backdrop { background: var(--pl-scrim); }
.pl-sheet[open] { animation: pl-rise 320ms var(--pl-spring); }
@keyframes pl-rise { from { transform: translateY(40px); opacity: 0; } }
@media (min-width: 640px) { .pl-sheet { margin: auto; width: min(480px, 92vw); border-radius: var(--pl-radius-xl); padding-top: var(--pl-5); }
  .pl-sheet::before { display: none; } }

/* The main action on a phone: pinned over the content on a material, safe area included.
   From 768 px it goes back in the flow, sized to its label. */
.pl-action-bar { position: sticky; bottom: 0; z-index: 10; margin-inline: calc(var(--pl-gutter) * -1); padding: 12px var(--pl-gutter) max(12px, var(--pl-safe-b));
  background: color-mix(in srgb, var(--pl-bg) 78%, transparent); backdrop-filter: saturate(180%) blur(20px); -webkit-backdrop-filter: saturate(180%) blur(20px);
  border-top: 1px solid var(--pl-separator); }
@media (min-width: 768px) { .pl-action-bar { position: static; margin-inline: 0; padding: 0; background: none; backdrop-filter: none; -webkit-backdrop-filter: none; border: 0; } }

/* A screen's one big title, the heading of a section under it, and the way back. Back names where it goes: <a class="pl-back" href="/minds">Minds</a> */
.pl-title { font: 700 var(--pl-title)/1.1 var(--pl-font-display); letter-spacing: var(--pl-tracking-title); }
.pl-heading { font: 700 var(--pl-heading)/1.2 var(--pl-font-display); letter-spacing: -0.02em; }
.pl-back { display: inline-flex; align-items: center; gap: 6px; min-height: var(--pl-control); color: var(--pl-accent-text); font: 500 var(--pl-button-size)/1.1 var(--pl-font); letter-spacing: var(--pl-tracking-control); text-decoration: none; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.pl-back::before { content: ""; width: 8px; height: 8px; margin-left: 2px; border: solid currentColor; border-width: 0 0 1.5px 1.5px; rotate: 45deg; }

/* Mobile first: the tab bar. Five or fewer, an icon and one word on each, on a material, above the
   home indicator. <nav class="pl-tabbar"><a aria-current="page">. From 768 px it moves to the top. */
.pl-tabbar { position: sticky; bottom: 0; z-index: 20; display: flex; padding-bottom: var(--pl-safe-b);
  background: color-mix(in srgb, var(--pl-bg) 92%, transparent); backdrop-filter: saturate(180%) blur(20px); -webkit-backdrop-filter: saturate(180%) blur(20px);
  border-top: 1px solid var(--pl-separator); }
.pl-tabbar a { flex: 1 1 0; min-height: 50px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  font-size: var(--pl-text-xs); line-height: 1.1; color: var(--pl-fg-muted); text-decoration: none; }
.pl-tabbar a svg { width: 24px; height: 24px; }
.pl-tabbar a[aria-current="page"] { color: var(--pl-accent-text); font-weight: 500; }
.pl-tabbar a[aria-current="page"] svg { fill: color-mix(in srgb, var(--pl-accent-text) 18%, transparent); }
@media (min-width: 768px) and (min-height: 501px) {
  .pl-tabbar { top: 0; bottom: auto; order: -1; justify-content: center; gap: 8px; border-top: 0; border-bottom: 1px solid var(--pl-separator); padding-bottom: 0; }
  .pl-tabbar a { flex: 0 0 auto; flex-direction: row; gap: 8px; padding-inline: 16px; font-size: var(--pl-secondary); }
  .pl-tabbar a svg { width: 20px; height: 20px; }
}

/* Mobile first: the home screen. A top row of filter chips with profile at the right, compact tiles for
   quick returns, then titled sections, with a continue bar above the tab bar.
   <header class="pl-topbar"><div class="pl-chips">…</div>…</header> */
.pl-topbar { position: sticky; top: 0; z-index: 20; display: flex; align-items: center; gap: var(--pl-1);
  padding: calc(var(--pl-1) + var(--pl-safe-t)) max(var(--pl-gutter), var(--pl-safe-r)) var(--pl-1) max(var(--pl-gutter), var(--pl-safe-l));
  background: color-mix(in srgb, var(--pl-bg) 92%, transparent); backdrop-filter: saturate(180%) blur(20px); -webkit-backdrop-filter: saturate(180%) blur(20px); }
.pl-chips { display: flex; flex: 1 1 auto; gap: 6px; min-width: 0; overflow-x: auto; scrollbar-width: none; padding-right: var(--pl-4);
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 20px), transparent); mask-image: linear-gradient(to right, #000 calc(100% - 20px), transparent); } /* fades where it's cut, so it reads as more */
.pl-chips::-webkit-scrollbar { display: none; }
.pl-chips .pl-chip { flex: none; }
.pl-tiles { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--pl-2); }
.pl-tile { display: flex; align-items: center; gap: var(--pl-3); min-height: 56px; min-width: 0; padding-right: var(--pl-2); overflow: hidden; border-radius: var(--pl-radius);
  background: var(--pl-fill); color: var(--pl-fg); text-decoration: none; font: 500 var(--pl-secondary)/1.2 var(--pl-font); }
.pl-tile > :first-child { flex: none; width: 56px; height: 56px; object-fit: cover; }
.pl-tile > :last-child { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
@media (hover: hover) { .pl-tile:hover { background: var(--pl-fill-hover); } }
@media (min-width: 768px) { .pl-tiles { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.pl-rail { display: flex; gap: var(--pl-3); overflow-x: auto; scrollbar-width: none; scroll-snap-type: x proximity;
  margin-inline: calc(var(--pl-gutter) * -1); padding-inline: var(--pl-gutter); scroll-padding-inline: var(--pl-gutter); }
.pl-rail::-webkit-scrollbar { display: none; }
.pl-rail > * { flex: none; scroll-snap-align: start; }
.pl-mini { position: sticky; bottom: calc(50px + var(--pl-safe-b)); z-index: 15; display: flex; align-items: center; gap: var(--pl-3); margin: 0 var(--pl-2) var(--pl-2); padding: var(--pl-1) var(--pl-1) var(--pl-1) var(--pl-1);
  overflow: hidden; border-radius: var(--pl-radius-control); background: var(--pl-surface); color: var(--pl-fg); text-decoration: none; box-shadow: 0 0 0 1px var(--pl-separator), var(--pl-shadow); }
.pl-mini::after { content: ""; position: absolute; left: 0; bottom: 0; height: 2px; width: var(--progress, 0%); background: var(--pl-accent); box-shadow: var(--pl-glow); }
@media (min-width: 768px) and (min-height: 501px) { .pl-mini { bottom: var(--pl-2); margin-inline: auto; width: min(560px, 100% - 32px); } }
/* NV9, one bar at the bottom: on a phone, a pinned main action takes the tab bar's place, and a live item rides above it.
   Put .pl-action-bar only on the screen that uses it, and only on an inner screen with a way back. */
@media (max-width: 767px) {
  body:has(.pl-action-bar) .pl-tabbar { display: none; }
  body:has(.pl-action-bar) .pl-mini { bottom: calc(var(--pl-control-lg) + 24px + var(--pl-safe-b)); }
}

/* iPad first: controls float over the canvas on a material, away from the content. */
.pl-float { display: flex; align-items: center; gap: 4px; padding: 4px; border-radius: 999px;
  background: color-mix(in srgb, var(--pl-surface) 76%, transparent); backdrop-filter: saturate(180%) blur(24px); -webkit-backdrop-filter: saturate(180%) blur(24px);
  box-shadow: 0 0 0 1px var(--pl-separator), 0 8px 24px color-mix(in srgb, var(--pl-ink) 14%, transparent); }
.pl-float { max-width: 100%; overflow-x: auto; scrollbar-width: none; } /* a narrow screen scrolls the tools, and never cuts them off */
.pl-float::-webkit-scrollbar { display: none; }
.pl-float > * { flex: none; }
.pl-float .pl-btn, .pl-float [data-slot="button"] { border-radius: var(--pl-radius-full); }

/* Stamps: identity, so they stay square and mono. */
.pl-stamp { font: 400 var(--pl-text-xs)/1.4 var(--pl-font-mono); letter-spacing: var(--pl-tracking-stamp); text-transform: uppercase;
  padding: 2px 6px; border: var(--pl-stamp-weight) solid var(--pl-fg); }
.pl-stamp--live { background: var(--pl-fg); color: var(--pl-bg); }
.pl-stamp--lab { border-style: dashed; }
.pl-stamp--retired { border-color: transparent; text-decoration: line-through; color: var(--pl-fg-muted); }
.pl-stamp--private { border-color: var(--pl-fg-muted); color: var(--pl-fg-muted); }
.pl-stamp--proven { background: var(--pl-fg); color: var(--pl-bg); }
.pl-stamp--unproven { border-style: dashed; }
.pl-stamp--local { border-style: solid; }

/* Status in a list, or anywhere a stamp would repeat: the word, beside the mark's square full stop.
   Filled for Live and Proven, hollow for Beta and Local, half for In the lab and Unproven. */
.pl-status { display: inline-flex; align-items: center; gap: 6px; font: 400 var(--pl-text-xs)/1.4 var(--pl-font-mono); color: var(--pl-fg-muted); white-space: nowrap; }
.pl-status::before, .pl-status--beta::before { content: ""; flex: none; width: 7px; height: 7px; box-shadow: inset 0 0 0 1px var(--pl-fg); }
.pl-status--live::before, .pl-status--proven::before { background: var(--pl-fg); }
.pl-status--lab::before, .pl-status--unproven::before { box-shadow: inset 0 0 0 1px var(--pl-fg), inset 3.5px 0 0 var(--pl-fg); }
.pl-status--private::before { box-shadow: inset 0 0 0 1px var(--pl-fg-muted); }
.pl-status--retired { text-decoration: line-through; }
.pl-status--retired::before { display: none; }

/* A tag only says something, so it's a small rounded rectangle and never a pill. */
.pl-tag { display: inline-flex; align-items: center; min-height: 24px; padding: 0 8px; border-radius: 6px; background: var(--pl-fill); color: var(--pl-fg-muted); font: 500 13px/1 var(--pl-font); letter-spacing: -0.003em; white-space: nowrap; }

@media (prefers-reduced-motion: reduce) {
  .pl-btn[aria-busy="true"]::before, .pl-skeleton, .pl-sheet[open] { animation: none; }
  .pl-switch::before { transition: none; }
}

/* Editorial compositions: image-led brand pages, product stories and campaign assets.
   Photos keep their color; the identity and all typography use the semantic roles. */
.pl-art-frame { margin: 0; min-width: 0; }
.pl-art-frame img { display: block; width: 100%; height: auto; aspect-ratio: 3 / 2; object-fit: cover; border-radius: var(--pl-radius-control); background: var(--pl-fill); }
.pl-art-frame figcaption { display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--pl-2) var(--pl-4); margin-top: var(--pl-3); color: var(--pl-fg-muted); font: 400 .75rem/1.5 var(--pl-font-mono); }
.pl-record { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--pl-2) var(--pl-4); font: 400 .75rem/1.5 var(--pl-font-mono); font-variant-numeric: tabular-nums; }
.pl-story { min-width: 0; }
.pl-story > .pl-record { margin-top: var(--pl-5); color: var(--pl-fg-muted); }
.pl-story h3 { margin: var(--pl-3) 0 var(--pl-2); font: 400 1.5rem/1.2 var(--pl-font); letter-spacing: -.025em; }
.pl-story h3 strong { font-weight: 800; }
.pl-story h3 a { display: flex; flex-wrap: wrap; align-items: center; gap: 0 .25em; min-height: var(--pl-touch); color: inherit; text-decoration: none; }
.pl-story h3 a > span { margin-left: auto; }
.pl-story > p { margin: 0; max-width: var(--pl-measure); font: 400 1.0625rem/1.55 var(--pl-font); color: var(--pl-fg-muted); }
.pl-poster { padding: var(--pl-6); border-radius: var(--pl-radius-control); background: var(--pl-surface); color: var(--pl-fg); }
.pl-poster__head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--pl-3); }
.pl-poster__head p { margin: 0; font: 400 1.0625rem/1.3 var(--pl-font); }
.pl-poster__head strong { font-weight: 800; }
.pl-poster h3 { margin: var(--pl-6) 0; max-width: 15ch; font: 900 clamp(1.875rem, 4vw, 4.5rem)/1.02 var(--pl-font); letter-spacing: -.03em; text-wrap: balance; overflow-wrap: anywhere; }
.pl-poster > .pl-record { margin-top: var(--pl-5); }
.pl-poster--image-first { display: flex; flex-direction: column; }
.pl-poster--image-first > .pl-art-frame { order: -1; margin-bottom: var(--pl-5); }
.pl-poster--type-first h3 { font-size: clamp(2.75rem, 6vw, 6.5rem); }
.pl-poster--type-first > .pl-art-frame { max-width: 60%; }
.pl-composition-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--pl-6); }
.pl-composition { display: block; min-width: 0; color: var(--pl-fg); text-decoration: none; }
.pl-composition figure { margin: 0; }
.pl-composition img { display: block; width: 100%; height: auto; aspect-ratio: 1; border-radius: var(--pl-radius-control); background: var(--pl-fill); }
.pl-composition figcaption { margin-top: var(--pl-3); font: 400 .75rem/1.5 var(--pl-font-mono); color: var(--pl-fg-muted); }
.pl-composition h3 { display: flex; justify-content: space-between; gap: var(--pl-3); margin: var(--pl-5) 0 var(--pl-2); font: 700 1.25rem/1.2 var(--pl-font); }
.pl-composition p { margin: 0; font: 400 1rem/1.55 var(--pl-font); color: var(--pl-fg-muted); }
@media (hover: hover) { .pl-composition:hover h3 { text-decoration: underline; text-underline-offset: .2em; } }
.pl-editorial { min-width: 0; }
.pl-evidence { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.5fr); gap: var(--pl-7); align-items: center; }
.pl-evidence h3 { margin: var(--pl-4) 0 var(--pl-5); max-width: 16ch; font: 700 clamp(1.5rem, 3vw, 2.75rem)/1.1 var(--pl-font); letter-spacing: -.025em; }
.pl-evidence p { max-width: var(--pl-measure); }
.pl-evidence p + p { margin-top: var(--pl-4); }
.pl-editorial__intro { display: grid; grid-template-columns: 1fr 1fr; gap: var(--pl-6); align-items: end; margin-bottom: var(--pl-6); }
.pl-editorial__title { margin: 0; font: 900 clamp(2.75rem, 5vw, 4.5rem)/1 var(--pl-font); letter-spacing: -.03em; text-wrap: balance; }
.pl-editorial__lead { margin: 0; max-width: var(--pl-measure); font: 400 1.25rem/1.4 var(--pl-font); color: var(--pl-fg-muted); }
.pl-editorial__link { display: inline-flex; align-items: center; gap: var(--pl-3); min-height: var(--pl-touch); margin-top: var(--pl-4); font: 500 1rem/1.3 var(--pl-font); color: var(--pl-fg); }
@media (max-width: 767px) {
  .pl-composition-grid { grid-template-columns: minmax(0, 1fr); }
  .pl-evidence { grid-template-columns: minmax(0, 1fr); gap: var(--pl-6); }
  .pl-editorial__intro { grid-template-columns: minmax(0, 1fr); gap: var(--pl-5); }
  .pl-poster { padding: var(--pl-5); }
}

/* Material (ST10, ST11): a real surface in real light, from materials/, beside this file. Use one per screen, on what's big and quiet.
   <section class="pl-material pl-material--oxblood"><h1>…</h1></section>. Worlds are lit in an accent, materials are black and white. */
.pl-material { position: relative; isolation: isolate; overflow: hidden; border-radius: var(--pl-radius-xl); background: var(--pl-ink) center / cover no-repeat; color: var(--pl-white); box-shadow: var(--pl-rest); }
.pl-material--light { background-color: var(--pl-paper); color: var(--pl-ink); } /* for a light surface: plaster, stone, metal, sage */
.pl-material--dim::before { content: ""; position: absolute; inset: 0; z-index: -1; background: rgb(0 0 0 / .32); } /* when words have to sit on a mid-tone material: flat, so it stays honest about the image */
.pl-material .pl-btn--primary { background: var(--pl-white); color: var(--pl-ink); box-shadow: var(--pl-sheen), var(--pl-rest); } /* the light is the accent here, so the button stays out of its way */
.pl-material--light .pl-btn--primary { background: var(--pl-ink); color: var(--pl-white); }
.pl-material--citrus { background-image: image-set(url("materials/world-citrus-800.webp") 1x, url("materials/world-citrus-1600.webp") 2x); }
.pl-material--infrared { background-image: image-set(url("materials/world-infrared-800.webp") 1x, url("materials/world-infrared-1600.webp") 2x); }
.pl-material--ultramarine { background-image: image-set(url("materials/world-ultramarine-800.webp") 1x, url("materials/world-ultramarine-1600.webp") 2x); }
.pl-material--bronze { background-image: image-set(url("materials/world-bronze-800.webp") 1x, url("materials/world-bronze-1600.webp") 2x); }
.pl-material--sage { background-image: image-set(url("materials/world-sage-800.webp") 1x, url("materials/world-sage-1600.webp") 2x); }
.pl-material--oxblood { background-image: image-set(url("materials/world-oxblood-800.webp") 1x, url("materials/world-oxblood-1600.webp") 2x); }
.pl-material--concrete { background-image: image-set(url("materials/material-concrete-600.webp") 1x, url("materials/material-concrete-1200.webp") 2x); }
.pl-material--plaster { background-image: image-set(url("materials/material-plaster-600.webp") 1x, url("materials/material-plaster-1200.webp") 2x); }
.pl-material--stone { background-image: image-set(url("materials/material-stone-600.webp") 1x, url("materials/material-stone-1200.webp") 2x); }
.pl-material--metal { background-image: image-set(url("materials/material-metal-600.webp") 1x, url("materials/material-metal-1200.webp") 2x); }
.pl-material--fabric { background-image: image-set(url("materials/material-fabric-600.webp") 1x, url("materials/material-fabric-1200.webp") 2x); }
.pl-material--rock { background-image: image-set(url("materials/material-rock-600.webp") 1x, url("materials/material-rock-1200.webp") 2x); }

/* Pattern (ST12): a tile from patterns/, drawn in the text color. Put it on an empty, aria-hidden element, behind the words. */
.pl-pattern { display: block; background: currentColor; opacity: var(--pl-pattern-opacity, .22); pointer-events: none; -webkit-mask-repeat: repeat; mask-repeat: repeat; }
.pl-pattern--fins { -webkit-mask-image: url("patterns/fins.svg"); mask-image: url("patterns/fins.svg"); -webkit-mask-size: 12px; mask-size: 12px; }
.pl-pattern--hatch { -webkit-mask-image: url("patterns/hatch.svg"); mask-image: url("patterns/hatch.svg"); -webkit-mask-size: 16px; mask-size: 16px; }
.pl-pattern--dots { -webkit-mask-image: url("patterns/dots.svg"); mask-image: url("patterns/dots.svg"); -webkit-mask-size: 16px; mask-size: 16px; }
.pl-pattern--arcs { -webkit-mask-image: url("patterns/arcs.svg"); mask-image: url("patterns/arcs.svg"); -webkit-mask-size: 96px; mask-size: 96px; }
.pl-pattern--contours { -webkit-mask-image: url("patterns/contours.svg"); mask-image: url("patterns/contours.svg"); -webkit-mask-size: 160px; mask-size: 160px; }

/* Grain: the tooth of paper, on a big plain surface, so it stops looking like a screen color. */
.pl-grain { position: relative; isolation: isolate; }
.pl-grain::after { content: ""; position: absolute; inset: 0; z-index: 1; border-radius: inherit; background: var(--pl-grain); opacity: var(--pl-grain-opacity, .07); mix-blend-mode: overlay; pointer-events: none; }
