/* Pifilabs 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: #0A0A0A;
  --pl-paper: #FAFAFA;
  --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); /* a product sets ONE accent from the palette below */
  --pl-on-accent: var(--pl-paper); /* text on the accent; head.html's dark variant flips it */
  --pl-thumb: var(--pl-white); /* a switch's thumb. Ink only in dark with no accent, where the track is white */
  /* Accent palette (approved 2026-11-05): [on paper, on ink]. Inside the app: primary button, selection, progress, links, one chart series. Outside it, only the full stop of the app icon.
     Which product has which: "accent" in scripts/products-full.json. */
  --pl-cobalt: #1D4ED8;  --pl-cobalt-ink: #7AA2FF;
  --pl-violet: #6D28D9;  --pl-violet-ink: #B49CFF;
  --pl-magenta: #BE185D; --pl-magenta-ink: #F472B6;
  --pl-ember: #C2410C;   --pl-ember-ink: #FB923C;
  --pl-forest: #15803D;  --pl-forest-ink: #4ADE80;
  --pl-teal: #0F766E;    --pl-teal-ink: #2DD4BF;
  --pl-plum: #86198F;    --pl-plum-ink: #E879F9;
  --pl-ochre: #8A5A00;   --pl-ochre-ink: #FACC15;

  /* 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(10 10 10 / .14), 0 0 0 .5px rgb(10 10 10 / .05);   /* the selected segment, the switch thumb */
  --pl-shadow: 0 6px 24px rgb(10 10 10 / .10), 0 0 0 .5px rgb(10 10 10 / .06); /* only what floats: sheets, toasts, menus */

  /* 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-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);
  }
}
: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-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);
}

@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 shadcn/pifilabs.css: 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-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-accent); color: var(--pl-on-accent); }
@media (hover: hover) { .pl-btn--primary:hover { background: color-mix(in srgb, var(--pl-accent) 90%, transparent); } }
.pl-btn--text { background: transparent; padding: 0 var(--pl-2); color: var(--pl-accent); }
@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-back:focus-visible, .pl-mini:focus-visible,
.pl-toast button:focus-visible, .pl-toast a:focus-visible { outline: 2px solid var(--pl-accent); 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);
  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); 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); }
.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); } /* 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 1px var(--pl-separator); 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 1px var(--pl-separator); 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 { box-shadow: 0 0 0 .5px var(--pl-separator); } .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); } }
.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); 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); 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); font-weight: 500; }
.pl-tabbar a[aria-current="page"] svg { fill: color-mix(in srgb, var(--pl-accent) 18%, transparent); }
@media (min-width: 768px) and (min-height: 501px) {
  pifilabs-bar:has(+ .pl-topbar) { order: -2; } /* the lockup first, then the tabs */
  .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><pifilabs-profile></pifilabs-profile></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); }
pifilabs-bar:has(+ .pl-topbar) { --pl-bar-safe: 0px; } /* the top row holds the safe area */
.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); }
@media (min-width: 768px) and (min-height: 501px) { .pl-mini { bottom: var(--pl-2); margin-inline: auto; width: min(560px, 100% - 32px); } }

/* 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 { 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; }
}
