/* platform.css — Squaresmile Tools platform shell + dashboard (Phase 14 redesign).
   Faithful port of the design handoff stylesheet (design/platform.css — THE pixel
   source). Every class carries the p- prefix so nothing collides with vendored
   tool-page CSS (soundsense .dash-*, stage-plot body.app). Keyframe names are
   p-prefixed too (keyframes are document-global).
   Mapping notes: design .app → .p-shell (root; carries is-nav-open/is-nav-collapsed),
   design .shell → .p-body (inner flex row), design .tsub → .p-titem.
   Account/admin components live in platform-views.css. */

/* Tokens are scoped under .p-shell + .p-toast — NOT :root — so they cannot leak
   into tool-page content. .p-toast is included because platform.js appends
   JS-created toasts to document.body (outside #p-shell) and they must still
   resolve --tile / --text / --accent. */
.p-shell, .p-toast{
  --accent: #e3a948;            /* fresh honey — platform accent */
  --acc-bright: color-mix(in oklab, var(--accent) 78%, #fff);
  --acc-dim: color-mix(in oklab, var(--accent) 14%, transparent);
  --acc-line: color-mix(in oklab, var(--accent) 32%, transparent);
  --acc-glow: color-mix(in oklab, var(--accent) 55%, transparent);
  --shell: #0c0d0d;
  --rail: #101110;
  --line: #222220;
  --line-soft: #1a1a18;
  --tile: #161716;
  --tile-2: #131313;
  --field: #141413;
  --text: #f1ede4;
  --muted: #9a958a;
  --faint: #6c685f;
  --danger: #d98a72;
  --ok: #7fae7f;
  --serif: "Playfair Display", Georgia, serif;
  --sans: "Hanken Grotesk", system-ui, -apple-system, sans-serif;
  --mono: "JetBrains Mono", ui-monospace, monospace;
}

/* font/color set here (design relied on auth-shared body rules) so the shell is
   self-sufficient next to app.css */
.p-shell{min-height:100vh;display:flex;flex-direction:column;background:var(--shell);color:var(--text);font-family:var(--sans);}

/* ───────────────────────── top bar ───────────────────────── */
.p-tbar{
  position:sticky;top:0;z-index:40;
  display:flex;align-items:center;gap:14px;
  height:66px;padding:0 22px;
  background:color-mix(in oklab, var(--shell) 84%, transparent);
  backdrop-filter:blur(12px);
  border-bottom:1px solid var(--line-soft);
}
/* GAP-FILL: design hides the burger >920px; production keeps it visible at every
   width because it also drives the desktop sidebar collapse (preserved behavior,
   localStorage platform.dashCollapsed). */
.p-burger{
  width:38px;height:38px;flex:none;display:grid;place-items:center;
  background:var(--tile);border:1px solid var(--line);border-radius:9px;color:var(--text);cursor:pointer;
}
.p-burger:hover{border-color:var(--accent);color:var(--accent);}
.p-burger svg{width:18px;height:18px;}
.p-brand{display:flex;align-items:center;gap:11px;text-decoration:none;}
.p-brand .mark{
  width:30px;height:30px;border-radius:8px;border:1.5px solid var(--accent);
  display:grid;place-items:center;color:var(--accent);flex:none;
  box-shadow:0 0 0 0 var(--acc-glow);transition:box-shadow .3s;
}
.p-brand:hover .mark{box-shadow:0 0 18px -4px var(--acc-glow);}
.p-brand .mark svg{width:16px;height:16px;}
.p-brand .wm{font-family:var(--serif);font-weight:600;font-size:19px;color:var(--accent);letter-spacing:.2px;white-space:nowrap;}
.p-tbar-sp{flex:1;}

/* Ko-fi + Shop top-bar buttons */
.p-tbtn{
  display:inline-flex;align-items:center;gap:8px;white-space:nowrap;
  font-family:var(--sans);font-size:13px;font-weight:600;letter-spacing:.01em;
  padding:8px 13px;border-radius:8px;text-decoration:none;cursor:pointer;
  border:1px solid var(--line);background:var(--tile);color:var(--text);
  transition:border-color .16s, color .16s, background .16s, transform .12s;
}
.p-tbtn svg{width:15px;height:15px;}
.p-tbtn:hover{transform:translateY(-1px);}
.p-tbtn.kofi{color:#e6a6a0;border-color:color-mix(in oklab,#e08a6a 34%,transparent);}
.p-tbtn.kofi:hover{background:color-mix(in oklab,#e08a6a 14%,transparent);border-color:color-mix(in oklab,#e08a6a 55%,transparent);}
.p-tbtn.shop{color:var(--acc-bright);border-color:var(--acc-line);}
.p-tbtn.shop:hover{background:var(--acc-dim);border-color:var(--accent);}

/* THEME-02: platform light/dark toggle (v2.0). data-pf-theme is set by the
   <head> script + platform-theme.js; data-theme on the button mirrors it.
   Sun icon shows in light mode (click → go dark), moon icon in dark mode
   (click → go light) — the "current state" affordance used by macOS/iOS. */
.p-theme-toggle{
  width:38px;height:38px;flex:none;display:grid;place-items:center;
  background:var(--tile);border:1px solid var(--line);border-radius:9px;
  color:var(--muted);cursor:pointer;position:relative;
  transition:border-color .16s,color .16s,background .16s,transform .12s;
}
.p-theme-toggle:hover{transform:translateY(-1px);border-color:var(--accent);color:var(--accent);background:var(--acc-dim);}
.p-theme-toggle:focus-visible{outline:none;box-shadow:0 0 0 3px var(--acc-dim);}
.p-theme-ic{display:none;}
.p-theme-ic svg{width:18px;height:18px;}
.p-theme-sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0;}
/* default-state icon: sun in light mode (currently light → click for dark),
   moon in dark mode (currently dark → click for light). */
html[data-pf-theme="light"] .p-theme-ic--sun,
html[data-pf-theme="dark"]  .p-theme-ic--moon{display:grid;}
html:not([data-pf-theme]) .p-theme-ic--sun{display:grid;} /* head script guard */

.p-tbar-div{width:1px;height:26px;background:var(--line);margin:0 4px;}
.p-who{color:var(--muted);font-size:13.5px;white-space:nowrap;}
.p-logout{color:var(--accent);font-size:13.5px;text-decoration:none;border-bottom:1px solid var(--acc-line);padding-bottom:1px;white-space:nowrap;background:none;border-top:none;border-left:none;border-right:none;cursor:pointer;font-family:var(--sans);}
.p-logout:hover{color:var(--acc-bright);}

/* ───────────────────────── body shell ───────────────────────── */
.p-body{flex:1;display:flex;align-items:stretch;min-height:0;}

.p-side{
  width:262px;flex:none;display:flex;flex-direction:column;
  border-right:1px solid var(--line-soft);
  background:var(--rail);
  padding:18px 14px 16px;
  /* Full height: desktop pins it to one viewport and makes it sticky (see the
     ≥921px block); the ≤920px drawer uses fixed top/bottom. Either way the rail
     is the viewport's height (not the whole tall page), so the nav can scroll
     inside .p-side-scroll while the footer blocks stay pinned to the bottom. */
}
/* Nav list fills the space and scrolls internally (flex:1 + overflow), which
   keeps the Support / Storage / build-stamp footer pinned to the bottom of the
   rail — always in view, no longer flung to the bottom of a tall page. */
.p-side-scroll{display:flex;flex-direction:column;gap:3px;overflow-y:auto;flex:1;min-height:0;}
/* Nav items must not be flex-shrunk to fit the scroll area — otherwise an
   expanded .p-tree (overflow:hidden) gets compressed and clips the tool list
   (only the first few tools show; on a short phone drawer, none do). Keeping
   them at natural height makes the content overflow and .p-side-scroll scroll,
   so the whole tool list is reachable. */
.p-side-scroll > *{flex-shrink:0;}

.p-nitem{
  display:flex;align-items:center;gap:12px;width:100%;text-align:left;
  padding:10px 13px;border-radius:10px;
  background:none;border:1px solid transparent;
  color:var(--muted);font-family:var(--sans);font-size:14px;font-weight:500;
  cursor:pointer;position:relative;transition:background .15s,color .15s;text-decoration:none;
}
.p-nitem>svg{width:18px;height:18px;flex:none;color:var(--faint);transition:color .15s;}
.p-nitem:hover{background:var(--tile);color:var(--text);}
.p-nitem:hover>svg{color:var(--muted);}
.p-nitem.on{background:var(--acc-dim);color:var(--acc-bright);border-color:var(--acc-line);}
.p-nitem.on>svg{color:var(--accent);}
.p-nitem.on::before{content:"";position:absolute;left:-14px;top:8px;bottom:8px;width:3px;border-radius:0 3px 3px 0;background:var(--accent);}
.p-nitem .chev{margin-left:auto;width:15px;height:15px;color:var(--faint);transition:transform .22s;}
.p-nitem.exp .chev{transform:rotate(180deg);}
.p-nitem .ncount{margin-left:auto;font-size:11px;font-variant-numeric:tabular-nums;color:var(--faint);background:var(--tile);border:1px solid var(--line-soft);padding:1px 7px;border-radius:99px;}

/* tool tree — real app titles + colour-coded icon dots (--tc set inline).
   Collapse uses max-height (not the grid-template-rows 0fr/1fr trick): inside
   the ≤920px off-canvas drawer .p-side is position:fixed, and iOS Safari fails
   to repaint an animated grid-row track in a fixed/overflow container — the
   .open class toggles but the tree never visibly expands. max-height animates
   reliably everywhere. The cap clears the full tool list (~11 items ≈ 420px). */
.p-tree{overflow:hidden;max-height:0;transition:max-height .26s ease;}
.p-tree.open{max-height:640px;}
.p-tree-in{min-height:0;display:flex;flex-direction:column;gap:1px;padding:3px 0 6px;}
.p-titem{
  display:flex;align-items:center;gap:10px;text-align:left;
  background:none;border:none;cursor:pointer;
  padding:7px 12px 7px 14px;margin-left:14px;border-radius:8px;
  color:var(--muted);font-family:var(--sans);font-size:13px;font-weight:500;
  transition:color .15s,background .15s;text-decoration:none;
}
.p-titem .tdot,.p-titem .p-tdot{width:22px;height:22px;flex:none;border-radius:6px;display:grid;place-items:center;
  color:var(--tc);background:color-mix(in oklab,var(--tc) 15%,transparent);border:1px solid color-mix(in oklab,var(--tc) 28%,transparent);}
.p-titem .tdot svg,.p-titem .p-tdot svg{width:13px;height:13px;}
.p-titem:hover{background:var(--tile);color:var(--text);}
.p-titem.cur{color:var(--text);background:var(--tile);}
.p-titem .tsoon{margin-left:auto;font-size:9px;letter-spacing:.1em;text-transform:uppercase;color:var(--faint);}

/* sidebar: labels, pinned, mini storage */
.p-side-label{font-size:10px;font-weight:700;letter-spacing:.18em;text-transform:uppercase;color:var(--faint);margin:14px 8px 7px;display:flex;align-items:center;gap:7px;}
.p-side-label:first-child{margin-top:2px;}
.p-sl-count{font-size:10px;color:var(--faint);background:var(--tile);border:1px solid var(--line-soft);padding:0 6px;border-radius:99px;line-height:16px;}
.p-pin-hint{display:flex;align-items:center;gap:8px;font-size:12px;line-height:1.45;color:var(--faint);margin:0 8px;padding:9px 11px;border:1px dashed var(--line);border-radius:9px;}
.p-pin-hint svg{width:14px;height:14px;flex:none;color:var(--accent);}
.p-pin-list{display:flex;flex-direction:column;gap:1px;}
.p-pinrow{display:flex;align-items:center;border-radius:8px;transition:background .14s;}
.p-pinrow:hover{background:var(--tile);}
.p-pinrow.cur{background:var(--tile);}
/* .p-pinrow-label is an alias for .p-pinrow-main — platform.js renderPins() (14-02)
   emits .p-pinrow > .p-tdot + .p-pinrow-label */
.p-pinrow-main,.p-pinrow-label{flex:1;min-width:0;display:flex;align-items:center;gap:10px;text-align:left;background:none;border:none;cursor:pointer;color:var(--muted);font-family:var(--sans);font-size:13px;font-weight:500;padding:7px 6px 7px 8px;text-decoration:none;}
.p-pinrow:hover .p-pinrow-main,.p-pinrow:hover .p-pinrow-label{color:var(--text);}
.p-pinrow .tdot,.p-pinrow .p-tdot{width:22px;height:22px;flex:none;border-radius:6px;display:grid;place-items:center;color:var(--tc);background:color-mix(in oklab,var(--tc) 15%,transparent);border:1px solid color-mix(in oklab,var(--tc) 28%,transparent);}
.p-pinrow .tdot svg,.p-pinrow .p-tdot svg{width:13px;height:13px;}
.p-pin-off{width:28px;height:28px;flex:none;display:grid;place-items:center;background:none;border:none;cursor:pointer;color:var(--accent);border-radius:7px;margin-right:4px;}
.p-pin-off svg{width:14px;height:14px;fill:var(--accent);}
.p-pin-off:hover{background:var(--acc-dim);}

/* sidebar support card */
.p-support-card{
  margin-top:14px;border-radius:13px;padding:15px 15px 14px;
  background:
    radial-gradient(120% 100% at 100% 0%, color-mix(in oklab,#e08a6a 12%,transparent), transparent 60%),
    var(--tile);
  border:1px solid var(--line);
}
.p-support-card h5{margin:0 0 3px;font-family:var(--serif);font-weight:600;font-size:15px;color:var(--text);}
.p-support-card p{margin:0 0 12px;font-size:12px;line-height:1.5;color:var(--muted);}
.p-support-row{display:flex;flex-direction:column;gap:8px;}
.p-sbtn{
  display:flex;align-items:center;gap:9px;text-decoration:none;cursor:pointer;white-space:nowrap;
  padding:9px 11px;border-radius:9px;font-size:12.5px;font-weight:600;
  border:1px solid var(--line);transition:transform .12s,border-color .16s,background .16s;
}
.p-sbtn svg{width:15px;height:15px;flex:none;}
.p-sbtn .arr{margin-left:auto;width:14px;height:14px;opacity:.6;}
.p-sbtn:hover{transform:translateY(-1px);}
.p-sbtn.kofi{color:#e6a6a0;background:color-mix(in oklab,#e08a6a 10%,transparent);border-color:color-mix(in oklab,#e08a6a 30%,transparent);}
.p-sbtn.kofi:hover{border-color:color-mix(in oklab,#e08a6a 55%,transparent);}
.p-sbtn.shop{color:var(--acc-bright);background:var(--acc-dim);border-color:var(--acc-line);}
.p-sbtn.shop:hover{border-color:var(--accent);}

.p-side-storage{margin-top:14px;padding:11px 12px;border-radius:10px;background:var(--tile);border:1px solid var(--line-soft);cursor:pointer;transition:border-color .15s;display:block;text-decoration:none;}
.p-side-storage:hover{border-color:var(--line);}
.p-ss-top{display:flex;align-items:center;justify-content:space-between;font-size:11.5px;font-weight:600;color:var(--muted);margin-bottom:7px;}
.p-ss-pct{font-variant-numeric:tabular-nums;color:var(--ok);}
.p-ss-bar{height:5px;border-radius:99px;background:var(--tile-2);overflow:hidden;}
.p-ss-bar i{display:block;height:100%;border-radius:99px;background:linear-gradient(90deg,var(--ok),color-mix(in oklab,var(--ok) 55%,var(--accent)));}
.p-ss-sub{font-size:10.5px;color:var(--faint);margin-top:6px;font-family:var(--mono);}

.p-side-meta{margin-top:14px;padding-top:13px;border-top:1px solid var(--line-soft);font-family:var(--mono);font-size:10.5px;line-height:1.7;color:var(--faint);}
.p-side-meta .ver{color:var(--accent);float:right;}

/* mobile-drawer-only support links — hidden on the desktop rail (≥921px);
   shown inside the off-canvas drawer at ≤920px where the card is hidden */
.p-side-support-m{display:none;margin-top:8px;}

/* ───────────────────────── content ───────────────────────── */
/* Motion contract: transform-only entrances — NEVER animate opacity from 0
   (paused-animation invisibility bug). The toast p-tin keyframe below is the
   sole sanctioned opacity fade. */
/* NOTE: no `both`/`forwards` fill — a transform-keyframe animation that keeps filling
   leaves .p-view as a persistent stacking context + fixed-positioning containing block,
   which traps tool tooltips/overlays (z-index:60) BENEATH the sticky topbar (.p-tbar
   z-index:40) and was the root of the device-gate black-screen. Without fill, the entrance
   still plays (delay:0 → starts at the `from` frame, no flash) but the context is released
   after 0.4s so in-tool popovers can paint above the topbar. */
.p-view{flex:1;min-width:0;padding:34px 38px 28px;animation:p-viewin .4s cubic-bezier(.2,.7,.2,1);}
@keyframes p-viewin{from{transform:translateY(8px);}to{transform:none;}}
@media (prefers-reduced-motion:reduce){.p-view,.p-tile{animation:none!important;}}

.p-vhead{display:flex;align-items:flex-end;justify-content:space-between;gap:20px;flex-wrap:wrap;margin:0 0 8px;}
.p-vtitle{font-family:var(--serif);font-weight:600;font-size:40px;line-height:1.04;letter-spacing:.3px;color:var(--text);margin:0;}
.p-vtitle .dot{color:var(--accent);}
.p-vsub{color:var(--muted);font-size:14.5px;margin:7px 0 0;}
.p-eyebrow{font-size:11px;font-weight:700;letter-spacing:.2em;text-transform:uppercase;color:var(--faint);margin:30px 0 14px;}

/* ── dashboard: support banner ── */
.p-promo{
  display:flex;align-items:center;gap:22px;flex-wrap:wrap;
  margin:20px 0 4px;padding:20px 22px;border-radius:15px;
  background:
    radial-gradient(140% 130% at 0% 0%, var(--acc-dim), transparent 55%),
    radial-gradient(140% 130% at 100% 100%, color-mix(in oklab,#e08a6a 13%,transparent), transparent 55%),
    var(--tile);
  border:1px solid var(--line);
}
.p-promo-ic{width:46px;height:46px;flex:none;border-radius:12px;display:grid;place-items:center;color:var(--accent);
  background:var(--acc-dim);border:1px solid var(--acc-line);}
.p-promo-ic svg{width:23px;height:23px;}
.p-promo-txt{flex:1;min-width:200px;}
.p-promo-txt h3{margin:0 0 3px;font-family:var(--serif);font-weight:600;font-size:19px;color:var(--text);}
.p-promo-txt p{margin:0;font-size:13.5px;line-height:1.5;color:var(--muted);}
.p-promo-cta{display:flex;gap:10px;flex-wrap:wrap;}
.p-pbtn{display:inline-flex;align-items:center;gap:8px;text-decoration:none;cursor:pointer;white-space:nowrap;
  padding:10px 16px;border-radius:9px;font-size:13.5px;font-weight:600;transition:transform .12s,background .16s,box-shadow .16s;}
.p-pbtn svg{width:16px;height:16px;}
.p-pbtn:hover{transform:translateY(-1px);}
.p-pbtn.solid{background:var(--accent);color:#1a1408;box-shadow:0 10px 28px -14px var(--acc-glow);}
.p-pbtn.solid:hover{background:var(--acc-bright);}
.p-pbtn.coffee{background:color-mix(in oklab,#e08a6a 16%,transparent);color:#e6a6a0;border:1px solid color-mix(in oklab,#e08a6a 36%,transparent);}
.p-pbtn.coffee:hover{background:color-mix(in oklab,#e08a6a 24%,transparent);}
.p-install-hint{display:flex;align-items:center;gap:8px;margin:12px 0 0;font-size:13px;color:var(--muted);}
.p-install-hint svg{width:16px;height:16px;flex:none;color:var(--accent);}
.p-install-hint a{color:var(--accent);}

/* ── filter chips ── */
.p-filters{display:flex;flex-wrap:wrap;gap:9px;margin:6px 0 20px;}
.p-chip{font-size:12.5px;font-weight:600;padding:7px 13px;border-radius:99px;cursor:pointer;
  background:var(--tile);border:1px solid var(--line-soft);color:var(--muted);transition:all .15s;display:inline-flex;align-items:center;gap:7px;font-family:var(--sans);}
.p-chip:hover{border-color:var(--line);color:var(--text);}
.p-chip.on{background:var(--acc-dim);border-color:var(--acc-line);color:var(--acc-bright);}
.p-chip .c{opacity:.65;font-variant-numeric:tabular-nums;}
.p-chip.on .c{opacity:.85;}

/* ── tool list (screenshot rows) ── */
.p-tools-grid{display:flex;flex-direction:column;gap:12px;}
.p-tile{
  position:relative;display:flex;align-items:center;gap:20px;
  background:var(--tile);border:1px solid var(--line-soft);border-radius:14px;
  padding:14px 18px 14px 14px;cursor:pointer;overflow:hidden;text-decoration:none;
  transition:border-color .18s,transform .18s,box-shadow .18s,background .18s;
  animation:p-tilein .5s both;
}
@keyframes p-tilein{from{transform:translateY(12px);}to{transform:none;}}
.p-tile::after{content:"";position:absolute;inset:0;border-radius:14px;pointer-events:none;opacity:0;transition:opacity .25s;
  background:radial-gradient(120% 120% at 0% 50%, color-mix(in oklab,var(--tc) 12%,transparent), transparent 52%);}
.p-tile:hover{transform:translateY(-2px);border-color:color-mix(in oklab,var(--tc) 50%,transparent);box-shadow:0 18px 44px -30px #000, 0 0 0 1px color-mix(in oklab,var(--tc) 22%,transparent);}
.p-tile:hover::after{opacity:1;}
.p-tile.soon{cursor:default;opacity:.66;}
.p-tile.soon:hover{transform:none;border-color:var(--line-soft);box-shadow:none;}
.p-tile.soon:hover::after{opacity:0;}

/* screenshot thumbnail (fresh per-tool captures; placeholder hatch when none) */
.p-tile-shot{position:relative;flex:none;width:172px;height:104px;border-radius:10px;overflow:hidden;
  background:#101010;border:1px solid var(--line-soft);}
.p-tile-shot img{width:100%;height:100%;object-fit:cover;object-position:center top;display:block;
  transition:transform .45s cubic-bezier(.2,.7,.2,1);}
.p-tile:hover .p-tile-shot img{transform:scale(1.05);}
.p-tile-shot.ph{display:grid;place-items:center;
  background:
    repeating-linear-gradient(135deg, color-mix(in oklab,var(--tc) 7%,transparent) 0 10px, transparent 10px 20px),
    color-mix(in oklab,var(--tc) 9%,#141413);
  border-color:color-mix(in oklab,var(--tc) 24%,transparent);}
.p-tile-shot .ph-ic{display:grid;place-items:center;color:var(--tc);opacity:.85;}
.p-tile-shot .ph-ic svg{width:30px;height:30px;}
/* small brand-colour icon chip pinned on the thumbnail */
.p-tile-ic{position:absolute;left:9px;bottom:9px;width:30px;height:30px;border-radius:8px;display:grid;place-items:center;color:var(--tc);
  background:color-mix(in oklab,#0c0d0d 64%,transparent);backdrop-filter:blur(6px);
  border:1px solid color-mix(in oklab,var(--tc) 34%,transparent);transition:transform .2s,box-shadow .25s;}
.p-tile-shot.ph .p-tile-ic{display:none;}
.p-tile-ic svg{width:16px;height:16px;}
.p-tile:hover .p-tile-ic{transform:scale(1.08);box-shadow:0 0 18px -6px color-mix(in oklab,var(--tc) 70%,transparent);}

.p-tile-body{flex:1;min-width:0;}
.p-tile-h{display:flex;align-items:center;gap:10px;flex-wrap:wrap;}
.p-tile-name{font-family:var(--serif);font-weight:600;font-size:19px;line-height:1.15;color:var(--text);}
.p-tile.soon .p-tile-name{color:#b7b2a7;}

/* status badges (design .tile-badge/.b-* → .p-badge/.p-badge--*) */
.p-badge{font-size:9.5px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;display:inline-flex;align-items:center;gap:4px;padding:3px 7px;border-radius:5px;}
.p-badge svg{width:11px;height:11px;}
.p-badge--free{background:var(--acc-dim);color:var(--acc-bright);border:1px solid var(--acc-line);}
.p-badge--unlocked{background:color-mix(in oklab,var(--ok) 16%,transparent);color:#9bd09b;border:1px solid color-mix(in oklab,var(--ok) 34%,transparent);}
.p-badge--premium{background:color-mix(in oklab,#d9a441 14%,transparent);color:#e0bd6e;border:1px solid color-mix(in oklab,#d9a441 32%,transparent);}
.p-badge--soon{background:#212019;color:var(--faint);border:1px solid var(--line-soft);}
/* GAP-FILL: maintenance badge (not in the design handoff) — amber-orange family
   per CONTEXT/UI-SPEC decision; tile stays clickable for admins per existing logic. */
.p-badge--maintenance{background:rgba(214,138,60,.16);color:#e0a567;border:1px solid rgba(214,138,60,.34);}

/* device-fit chip — surfaces a tool's min_device (sits inline with the badge) */
.p-tile-device{display:inline-flex;align-items:center;gap:4px;font-size:9px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--faint);padding:3px 7px;border-radius:5px;background:#212019;border:1px solid var(--line-soft);white-space:nowrap;}
.p-tile-device svg{width:11px;height:11px;flex:none;}

.p-tile-desc{color:var(--muted);font-size:13.5px;line-height:1.5;margin:6px 0 0;text-wrap:pretty;}

.p-tile-cta{flex:none;display:flex;align-items:center;gap:8px;}
.p-tile-link{display:inline-flex;align-items:center;gap:7px;font-size:13px;font-weight:600;color:var(--tc);transition:gap .15s;white-space:nowrap;text-decoration:none;}
.p-tile-link svg{width:15px;height:15px;}
.p-tile:hover .p-tile-link{gap:11px;}
.p-tile-link.muted{color:var(--faint);}

.p-fav{flex:none;width:32px;height:32px;display:grid;place-items:center;border-radius:8px;
  background:none;border:1px solid transparent;color:var(--faint);cursor:pointer;transition:all .15s;z-index:2;}
.p-fav:hover{color:var(--accent);background:var(--acc-dim);}
.p-fav.on{color:var(--accent);}
.p-fav svg{width:16px;height:16px;}
.p-fav.on svg{fill:var(--accent);}

/* ───────────────────────── toast / footer / scrim ───────────────────────── */
.p-toast{position:fixed;left:50%;bottom:26px;transform:translateX(-50%);background:var(--tile);border:1px solid var(--line);color:var(--text);padding:12px 18px;border-radius:10px;font-size:14px;display:flex;align-items:center;gap:9px;box-shadow:0 22px 50px -20px #000;z-index:60;animation:p-tin .25s;font-family:var(--sans);}
/* p-tin is the ONLY sanctioned opacity-from-0 fade (short, non-blocking, kept in the final handoff) */
@keyframes p-tin{from{opacity:0;transform:translate(-50%,8px);}to{opacity:1;transform:translate(-50%,0);}}
.p-toast svg{width:17px;height:17px;color:var(--accent);}
/* GAP-FILL: error flash variant (14-04 shell) — session('error') toasts get a
   danger-tinted border + icon so failures read differently from successes. */
.p-toast--err{border-color:color-mix(in oklab,var(--danger) 45%,transparent);}
.p-toast--err svg{color:var(--danger);}

.p-foot{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:8px 24px;padding:22px 24px;border-top:1px solid var(--line-soft);color:var(--faint);font-size:12.5px;}
.p-foot a{color:var(--faint);text-decoration:none;transition:color .15s;}
.p-foot a:hover{color:var(--muted);}
.p-foot .sep{opacity:.4;}

.p-scrim{position:fixed;inset:0;background:rgba(0,0,0,.55);z-index:35;border:none;display:none;}

.p-burger:focus-visible,.p-fav:focus-visible{outline:none;box-shadow:0 0 0 3px var(--acc-dim);}

/* ───────── desktop sidebar collapse (GAP-FILL — not in the design) ─────────
   Locked preserved behavior: burger toggles .is-nav-collapsed on #p-shell
   (localStorage platform.dashCollapsed). Discretion choice: the sidebar is fully
   hidden (display:none) and .p-view's flex:1 lets content span the full width —
   simplest faithful read of "collapsed", no icon-rail mode in the handoff.
   Gated to >920px so it never fights the off-canvas drawer below. */
@media (min-width:921px){
  .p-shell.is-nav-collapsed .p-side{display:none;}
  /* Desktop rail: full viewport height (fills to the bottom), sticky under the
     top bar, self-scrolling. align-self:flex-start opts out of .p-body's
     align-items:stretch (which would stretch it to the full, possibly very tall
     page height); the explicit height then pins it to one viewport so the rail
     stays put and scrolls internally while content flows from the top. */
  .p-side{position:sticky;top:66px;align-self:flex-start;height:calc(100vh - 66px);}
}

/* ───────────────────────── responsive ───────────────────────── */
@media (max-width:1080px){
  .p-who{display:none;}
}
@media (max-width:920px){
  .p-side{position:fixed;top:66px;bottom:0;left:0;z-index:38;transform:translateX(-100%);transition:transform .26s ease;box-shadow:0 0 60px -10px rgba(0,0,0,.8);}
  .p-shell.is-nav-open .p-side{transform:none;}
  .p-shell.is-nav-open .p-scrim{display:block;}
  .p-view{padding:28px 22px;}
  .p-vtitle{font-size:32px;}
  .p-tbtn .lbl{display:none;}
  .p-support-card{display:none;}
  .p-side-support-m{display:block;}
}
@media (max-width:620px){
  .p-brand .wm{display:none;}
  .p-tbtn.shop,.p-tbtn.kofi,.p-tbar-div{display:none;}
  .p-vtitle{font-size:27px;}
  .p-promo{flex-direction:column;align-items:flex-start;gap:16px;}
  .p-promo-txt{min-width:0;}
  .p-promo-cta{flex-direction:column;width:100%;}
  .p-promo .p-pbtn{width:100%;}
  .p-view{padding:20px 16px;}
  .p-burger{width:44px;height:44px;}
  /* screenshot rows reflow: thumbnail shrinks, CTA drops to its own full-width line */
  .p-tile{flex-wrap:wrap;gap:13px;padding:13px;}
  .p-tile-shot{width:96px;height:64px;}
  .p-tile-cta{width:100%;justify-content:space-between;order:3;border-top:1px solid var(--line-soft);padding-top:11px;}
  .p-fav{width:44px;height:44px;}
}

/* "What's New" nav badge — gold dot when there are unseen releases.
   Toggled by public/js/changelog-badge.js (.has-unread). */
#nav-whats-new.has-unread::after {
  content: '';
  width: 7px;
  height: 7px;
  margin-left: 6px;
  border-radius: 50%;
  background: var(--accent);
  flex: 0 0 auto;
  animation: cl-navpulse 2s infinite;
}

@keyframes cl-navpulse {
  0%, 100% { box-shadow: 0 0 0 0 var(--acc-glow); }
  50%      { box-shadow: 0 0 0 5px transparent; }
}

@media (prefers-reduced-motion: reduce) {
  #nav-whats-new.has-unread::after { animation: none; }
}

/* ── LOCALE-01: universal language picker (topbar) ─────────────────────────
   Matches the .p-tbtn chrome; native select arrow kept (no appearance:none)
   so no data-URI caret is needed under the enforced CSP. */
.p-lang{display:inline-flex;align-items:center;gap:7px;}
.p-lang-ic{display:inline-flex;color:var(--muted);}
.p-lang-ic svg{width:15px;height:15px;}
.p-lang-select{
  font-family:var(--sans);font-size:13px;font-weight:600;letter-spacing:.01em;
  padding:7px 9px;border-radius:8px;cursor:pointer;
  border:1px solid var(--line);background:var(--tile);color:var(--text);
  transition:border-color .16s;
}
.p-lang-select:hover,
.p-lang-select:focus-visible{border-color:var(--acc-line);}
