/* generated by scripts/sync-studio.mjs from apps/studio/assets/styles.css — do not edit */
@keyframes hintin{from{opacity:0;transform:translate(-50%,-4px)}to{opacity:1;transform:translate(-50%,0)}}
@keyframes spin{to{transform:rotate(360deg)}}
@keyframes justsaved{0%{box-shadow:0 0 0 0 rgba(74,87,236,.55)}60%{box-shadow:0 0 0 9px rgba(74,87,236,0)}100%{box-shadow:0 0 0 0 rgba(74,87,236,0)}}
@scope (.leora-studio) {
/* ───────────────────────────── tokens ─────────────────────────────
   Taken from the iOS app: Packages/LeoraUI/Sources/LeoraUI/DesignTokens.swift
     background .949/.949/.969   surface white     canvas .925/.925/.945
     bone .937/.937/.918         boneDim .875/.875/.851
     ink .07/.07/.08             inkSoft ink@55%   hairline ink@8%
     brass .290/.340/.925        glow 1/.93/.82    limit .77/.36/.28
   Radii: card 26, control 16.                                              */
:scope{
  color-scheme:light;
  --paper:#F2F2F7;            /* LeoraColor.background */
  --paper-2:#FFFFFF;          /* LeoraColor.surface    */
  --surface:#ECECF1;          /* LeoraColor.canvas     */
  --bone:#EFEFEA;
  --bone-dim:#DFDFD9;
  --ink:#121214;
  --ash:rgba(18,18,20,.55);   /* LeoraColor.inkSoft    */
  --ash-2:rgba(18,18,20,.38);
  --hairline:rgba(18,18,20,.08);
  --hairline-2:rgba(18,18,20,.17);
  --filament:#4A57EC;         /* LeoraColor.brass — the app's accent */
  --glow:#FFEDD1;
  --bad:#C45C47;              /* LeoraColor.limit      */
  --viewport:#ECECF1;
  --viewport-2:#F2F2F7;
  --sweep-top:#F2F2F7;
  --sweep-bot:#DFDFD9;
  --nav-bg:rgba(242,242,247,.82);
  --scrim:rgba(18,18,20,.34);
  --focus:#4A57EC;
  --shadow:0 24px 60px -24px rgba(18,18,26,.26);
  --r-card:26px;              /* LeoraRadius.card    — tokens.json radius.card    */
  --r-control:16px;           /* LeoraRadius.control — tokens.json radius.control */
}
@media (prefers-color-scheme: dark){
  :scope:not([data-theme="light"]){
    color-scheme:dark;
    --paper:#0E0E12; --paper-2:#17171E; --surface:#1D1D25;
    --bone:#23232B; --bone-dim:#2A2A33;
    --ink:#F2F2F7;
    --ash:rgba(242,242,247,.58); --ash-2:rgba(242,242,247,.40);
    --hairline:rgba(242,242,247,.10); --hairline-2:rgba(242,242,247,.19);
    --filament:#8B94F7; --glow:#FFEDD1; --bad:#E0806B;
    --viewport:#17171E; --viewport-2:#0E0E12;
    --sweep-top:#1C1C24; --sweep-bot:#0C0C10;
    --nav-bg:rgba(14,14,18,.80); --scrim:rgba(0,0,0,.62); --focus:#8B94F7;
    --shadow:0 24px 60px -24px rgba(0,0,0,.7);
  }
}
:scope[data-theme="dark"]{
  color-scheme:dark;
  --paper:#0E0E12; --paper-2:#17171E; --surface:#1D1D25;
  --bone:#23232B; --bone-dim:#2A2A33;
  --ink:#F2F2F7;
  --ash:rgba(242,242,247,.58); --ash-2:rgba(242,242,247,.40);
  --hairline:rgba(242,242,247,.10); --hairline-2:rgba(242,242,247,.19);
  --filament:#8B94F7; --glow:#FFEDD1; --bad:#E0806B;
  --viewport:#17171E; --viewport-2:#0E0E12;
  --sweep-top:#1C1C24; --sweep-bot:#0C0C10;
  --nav-bg:rgba(14,14,18,.80); --scrim:rgba(0,0,0,.62); --focus:#8B94F7;
  --shadow:0 24px 60px -24px rgba(0,0,0,.7);
}
/* ───────────────────────────── base ───────────────────────────── */
*{box-sizing:border-box}
img,video{max-width:100%;display:block}
[hidden]{display:none!important}
:scope{-webkit-text-size-adjust:100%}
:scope{
  margin:0;background:var(--paper);color:var(--ink);
  font-family:'Instrument Sans',ui-sans-serif,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
  font-size:16px;line-height:1.55;-webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}
h1,h2,h3,h4{margin:0;text-wrap:balance;font-weight:500;letter-spacing:-.035em;line-height:1.05}
p{margin:0}
a{color:inherit;text-decoration:none}
button{font:inherit;color:inherit;background:none;border:none;padding:0;cursor:pointer}
ul{margin:0;padding:0;list-style:none}
:focus-visible{outline:2px solid var(--focus);outline-offset:3px;border-radius:3px}
::selection{background:var(--glow);color:#111112}
.skip{position:absolute;left:-9999px;top:0;z-index:200;background:var(--ink);color:var(--paper);padding:10px 16px;border-radius:0 0 6px 0}
.skip:focus{left:0}
.wrap{width:100%;max-width:1180px;margin-inline:auto;padding-inline:18px}
@media(min-width:700px){.wrap{padding-inline:28px}}
.eyebrow{
  font-family:'IBM Plex Mono',ui-monospace,monospace;
  font-size:10.5px;font-weight:500;letter-spacing:.16em;text-transform:uppercase;color:var(--ash-2);
}
.serif{font-family:'Instrument Serif',Georgia,serif;font-style:italic;letter-spacing:-.01em;font-weight:400}
.mono{font-family:'IBM Plex Mono',ui-monospace,monospace;font-variant-numeric:tabular-nums}
.d1{font-size:clamp(2.35rem,8.5vw,5rem);letter-spacing:-.048em}
.d2{font-size:clamp(1.8rem,5.2vw,3rem);letter-spacing:-.042em}
.d3{font-size:clamp(1.2rem,3.2vw,1.6rem);letter-spacing:-.032em}
.lede{font-size:clamp(.98rem,2.6vw,1.15rem);line-height:1.55;color:var(--ash);max-width:58ch}
section{border-top:1px solid var(--hairline)}
.pad{padding-block:clamp(56px,9vw,124px)}
.sub-head{font-size:.95rem;letter-spacing:-.02em;color:var(--ash);margin:44px 0 18px}
.sec-head{display:flex;flex-direction:column;gap:16px;margin-bottom:32px}
.sec-note{font-size:14.5px;max-width:44ch}
@media(min-width:900px){
  .sec-head{flex-direction:row;align-items:flex-end;justify-content:space-between;gap:40px;margin-bottom:44px}
}
/* ───────────────────────────── nav ───────────────────────────── */
.nav{
  position:sticky;top:0;z-index:60;background:var(--nav-bg);
  backdrop-filter:saturate(180%) blur(18px);-webkit-backdrop-filter:saturate(180%) blur(18px);
  border-bottom:1px solid transparent;transition:border-color .3s ease;
}
.nav.stuck{border-bottom-color:var(--hairline)}
.nav-in{display:flex;align-items:center;gap:14px;height:58px}
.mark{display:flex;align-items:center;margin-right:auto;flex:none}
.mark img{height:19px;width:auto}
:scope[data-theme="dark"] .mark img{filter:invert(1) brightness(1.7)}
@media (prefers-color-scheme: dark){:scope:not([data-theme="light"]) .mark img{filter:invert(1) brightness(1.7)}}
.nav-links{display:none;gap:26px;font-size:13.5px;color:var(--ash)}
.nav-links a{transition:color .18s}
.nav-links a:hover,.nav-links a[aria-current]{color:var(--ink)}
@media(min-width:880px){.nav-links{display:flex;align-items:center}}
.nav-act{display:flex;align-items:center;gap:10px}
.iconbtn{
  width:38px;height:38px;display:grid;place-items:center;border-radius:999px;flex:none;
  color:var(--ash);transition:color .18s,background .18s;
}
.iconbtn:hover{color:var(--ink);background:var(--surface)}
.signin{display:none;font-size:13.5px;color:var(--ash)}
.signin:hover{color:var(--ink)}
@media(min-width:520px){.signin{display:inline}}
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
  min-height:40px;padding:0 17px;border-radius:999px;
  background:var(--ink);color:var(--paper);
  font-size:13.5px;font-weight:500;letter-spacing:-.01em;white-space:nowrap;
  transition:opacity .18s,transform .12s;
}
.btn:hover{opacity:.86}
.btn:active{transform:scale(.985)}
.btn-ghost{background:transparent;color:var(--ink);border:1px solid var(--hairline-2)}
.btn-ghost:hover{background:var(--surface);opacity:1}
.btn-lg{min-height:48px;padding:0 24px;font-size:15px}
.btn-sm{min-height:34px;padding:0 13px;font-size:12.5px}
.wide{width:100%}
.link-arrow{
  display:inline-flex;align-items:center;gap:7px;font-size:14px;color:var(--ink);
  border-bottom:1px solid var(--hairline-2);padding-bottom:3px;width:fit-content;
  transition:gap .2s,border-color .2s;
}
.link-arrow:hover{gap:11px;border-color:var(--ink)}
/* ───────────────────────────── hero ───────────────────────────── */
.hero{border-top:none;padding-block:clamp(36px,7vw,76px) clamp(24px,4vw,40px)}
.page-hero{padding-block:clamp(48px,9vw,104px) clamp(24px,4vw,44px)}
.hero-grid{display:flex;flex-direction:column;gap:32px}
.hero-copy .eyebrow{margin-bottom:18px}
.hero h1{margin-bottom:18px}
.hero .lede{margin-bottom:26px}
.hero-cta{display:flex;flex-wrap:wrap;gap:12px}
/* Every media box takes its clip's OWN aspect, so nothing is cropped:
   the hero clip is 1350 × 1080, the printing and assembly clips 1080 × 1080,
   the "slide through time" clip 600 × 1080 portrait, the growth frames
   1080 × 1080. A box of another shape with object-fit: cover cut them. */
.hero-media{margin:0;border-radius:var(--r-card);overflow:hidden;background:var(--surface);aspect-ratio:1350/1080}
.hero-media video{width:100%;height:100%;object-fit:cover}
@media(min-width:900px){
  .hero-grid{flex-direction:row;align-items:center;gap:56px}
  .hero-copy{flex:1 1 0;min-width:0}
  .hero-media{flex:1 1 0;min-width:0}
}
/* ───────────────────────────── studio ───────────────────────────── */
.studio{border-top:none;padding-bottom:clamp(48px,8vw,96px)}
/* The frame (17 Sep 26 — owner: "add roundness … this parameter window can
   float on the viewer rather than being a separate part"). On a wide screen
   the stage is ONE rounded card and the controls are a rounded glass panel
   floating over its right; Shuffle, the zoom pair and the readout float over
   it too, so the lamp has the whole card to itself and the camera centres it
   in the part the panel leaves free (studio.js: panelOverlap). On a phone
   the two are stacked rounded cards — a panel floating over a small screen
   would cover the lamp. */
.studio-frame{
  --panel-w:344px; --panel-gap:14px;
  display:flex;flex-direction:column;gap:12px;min-width:0;
}
.stage{
  position:relative;min-width:0;display:flex;flex-direction:column;
  border-radius:var(--r-card);border:1px solid var(--hairline);overflow:hidden;
  /* StudioView: LeoraColor.background, and the app's own comment on it is
     "flat — no gradients". A vertical sweep behind the lamp was mine; form
     comes from the three-point rig, not from the backdrop. */
  background:var(--viewport-2);
}
/* The canvas fills whatever height the frame ends up at, so the lamp is
   centred in the space rather than parked at the top of a fixed box, and
   the overlays anchor here instead of over the readout. */
.viewport{position:relative;flex:1 1 auto;min-height:340px}
#gl{display:block;position:absolute;inset:0;z-index:1;width:100%;height:100%;touch-action:none;cursor:grab}
@media(min-width:700px){.viewport{min-height:460px}}
#gl:active{cursor:grabbing}
/* No room glow behind the lamp when it is lit: the app's studio is
   LeoraColor.background, "flat — no gradients", and LeoraColor.glow is
   defined but never drawn. Light on changes the material and nothing else. */
.fallback{position:absolute;inset:0;display:none;place-items:center;padding:24px;color:var(--ash)}
.fallback.show{display:grid}
.fallback p{font-size:13.5px;text-align:center;max-width:34ch;line-height:1.5}
.stage-top{
  position:absolute;top:12px;left:12px;right:64px;z-index:3;
  display:flex;align-items:center;gap:10px;pointer-events:none;
}
.stage-left{display:flex;align-items:center;gap:8px;min-width:0;pointer-events:auto}
/* the app's glass pill and glass circle, on the stage over the lamp */
.glasspill{
  pointer-events:auto;display:inline-flex;align-items:center;gap:7px;
  min-height:40px;padding:0 14px;border-radius:999px;
  background:color-mix(in srgb,var(--paper-2) 78%,transparent);
  -webkit-backdrop-filter:saturate(180%) blur(14px);backdrop-filter:saturate(180%) blur(14px);
  border:1px solid var(--hairline-2);color:var(--ink);
  font-size:13px;font-weight:600;letter-spacing:-.01em;white-space:nowrap;
  box-shadow:0 8px 22px -14px rgba(18,18,26,.34);
  transition:transform .12s ease,border-color .18s;
}
.glasspill:hover{border-color:var(--ink)}
.glasspill:active{transform:scale(.965)}
.stage-zoom{
  position:absolute;top:12px;right:12px;z-index:3;
  display:flex;flex-direction:column;gap:8px;pointer-events:none;
}
.glassbtn{
  pointer-events:auto;width:40px;height:40px;display:grid;place-items:center;border-radius:999px;
  background:color-mix(in srgb,var(--paper-2) 78%,transparent);
  -webkit-backdrop-filter:saturate(180%) blur(14px);backdrop-filter:saturate(180%) blur(14px);
  border:1px solid var(--hairline-2);color:var(--ink);
  box-shadow:0 8px 22px -14px rgba(18,18,26,.34);
  transition:transform .12s ease,border-color .18s;
}
.glassbtn:hover{border-color:var(--ink)}
.glassbtn:active{transform:scale(.965)}
/* Copy.studio.heroHint — one pill, once, gone on the first drag */
.herohint{
  position:absolute;top:64px;left:50%;transform:translateX(-50%);z-index:3;
  display:none;align-items:center;gap:6px;pointer-events:none;
  padding:8px 12px;border-radius:999px;
  background:color-mix(in srgb,var(--paper-2) 78%,transparent);
  -webkit-backdrop-filter:saturate(180%) blur(14px);backdrop-filter:saturate(180%) blur(14px);
  border:1px solid var(--hairline-2);color:var(--ink);
  font-size:12px;font-weight:500;white-space:nowrap;
  animation:hintin .45s ease both;
}
.herohint.show{display:inline-flex}
/* The page nav is sticky and sits above the stage. Scrolled to the top of a
   phone screen it would cover the Shuffle and zoom controls, so on narrow
   viewports they start below it — the same reason the app parks its zoom
   stack at 108 pt, "clear of the transparent nav bar". */
@media(max-width:999px){
  .stage-top{top:66px}
  .stage-zoom{top:66px}
  /* under the zoom pair (66 + 2 × 40 + 8 px), so it never lies over the
     zoom-out button; as wide as the stage allows, on two centred lines when
     a language needs them (the site's Turkish, German …) */
  .herohint{top:162px;width:max-content;max-width:calc(100% - 24px);white-space:normal;text-align:center;line-height:1.35}
}
.tag{
  font-family:'IBM Plex Mono',ui-monospace,monospace;font-size:10px;
  letter-spacing:.1em;text-transform:uppercase;color:var(--ash-2);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.tag.dim{opacity:.62}
.stage-bottom{
  position:absolute;left:12px;right:12px;bottom:12px;
  display:flex;flex-wrap:wrap;gap:8px;pointer-events:none;
}
.seg{
  pointer-events:auto;display:inline-flex;padding:3px;gap:2px;
  border:1px solid var(--hairline-2);border-radius:999px;background:var(--paper-2);
}
.seg button{
  min-height:32px;padding:0 13px;border-radius:999px;font-size:12px;color:var(--ash);
  transition:background .18s,color .18s;white-space:nowrap;
}
.seg button[aria-pressed="true"]{background:var(--ink);color:var(--paper)}
.readout{
  display:flex;flex-wrap:wrap;align-items:center;gap:6px 18px;
  padding:11px 14px;border-top:1px solid var(--hairline);
  font-family:'IBM Plex Mono',ui-monospace,monospace;font-size:11px;
  color:var(--ash-2);font-variant-numeric:tabular-nums;
}
.readout .tile{display:inline-flex;align-items:baseline;gap:5px}
.readout .tile b{font-size:14px;font-weight:600;color:var(--ink)}
.readout .meta{flex:1 1 100%;opacity:.86;line-height:1.5}
.readout .ok{color:var(--filament);font-style:normal}
.readout .bad{color:var(--bad);font-style:normal}
/* ─── tray ─── */
.panel{
  display:flex;flex-direction:column;min-width:0;overflow:hidden;
  border-radius:var(--r-card);border:1px solid var(--hairline);background:var(--paper-2);
}
.tabs{display:grid;grid-template-columns:repeat(3,1fr);border-bottom:1px solid var(--hairline)}
.tabs button{
  min-height:46px;font-size:13px;color:var(--ash);
  border-bottom:2px solid transparent;transition:color .18s,border-color .18s;
}
.tabs button[aria-pressed="true"]{color:var(--ink);border-bottom-color:var(--ink)}
.tray{flex:1 1 auto;min-height:0;padding:16px 16px 4px;overflow-y:auto;max-height:none}
/* CoachCard: a brass-tinted well with the sparkle mark and its own "Got it",
   exactly the shape of the app's dismissible step hint. */
.thumb{display:inline-grid;place-items:center;flex:none;overflow:hidden}
.thumb canvas{display:block}
.coach{
  display:flex;align-items:flex-start;gap:10px;margin-bottom:16px;
  padding:12px;border-radius:18px;
  background:color-mix(in srgb,var(--filament) 9%,transparent);
}
.coach-mark{flex:none;color:var(--filament);margin-top:1px}
.coach-body{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}
.coach b{font-size:13px;font-weight:600;color:var(--ink);letter-spacing:-.01em}
.coach span{font-size:12px;color:var(--ash);line-height:1.45}
.coach-got{
  flex:none;align-self:flex-start;font-size:12px;font-weight:600;color:var(--ink);
  padding:6px 10px;border-radius:999px;background:var(--surface);
}
.coach-got:hover{background:var(--bone-dim)}
.coach-note{font-size:11.5px;color:var(--ash-2);margin-top:12px;line-height:1.45}
.srow{display:flex;flex-direction:column;gap:5px;padding:11px 0;border-bottom:1px solid var(--hairline);position:relative}
.srow:last-child{border-bottom:none}
.srow.quiet{padding-top:2px;border-bottom:none;opacity:.78}
.srow.marquee{padding-top:2px}
/* a value that cannot sit beside its label (a narrow phone, a long language)
   takes the next line, on the right, whole — rather than both wrapping */
.srow-head{display:flex;flex-wrap:wrap;align-items:baseline;justify-content:space-between;gap:2px 10px}
.srow-label{font-size:13px;color:var(--ash);display:inline-flex;align-items:center;gap:6px}
.srow-val{font-family:'IBM Plex Mono',ui-monospace,monospace;font-size:12.5px;font-weight:500;color:var(--ink);font-variant-numeric:tabular-nums;text-align:right;margin-left:auto;white-space:nowrap}
.srow.atlimit .srow-val{color:var(--bad)}
.srow.atlimit input[type=range]::-webkit-slider-runnable-track{background:color-mix(in srgb,var(--bad) 26%,var(--hairline-2))}
.srow-ends{display:flex;justify-content:space-between;font-size:10.5px;color:var(--ash-2)}
.rgroup{border-bottom:1px solid var(--hairline);padding-bottom:8px}
.rgroup:last-child{border-bottom:none}
.tipbtn{
  width:15px;height:15px;border-radius:999px;border:1px solid var(--hairline-2);
  font-size:9.5px;line-height:1;color:var(--ash-2);display:inline-grid;place-items:center;flex:none;
}
.tipbtn:hover{color:var(--ink);border-color:var(--ink)}
.tipbox{
  margin-top:6px;padding:9px 11px;border-radius:var(--r-control);background:var(--surface);
  font-size:11.5px;line-height:1.5;color:var(--ash);
}
/* under a tray header, the tip keeps the header's rhythm with what follows */
.tray-head + .tipbox{margin:0 0 12px}
/* Shuffle's tip floats under the stage's top row, in the glass of its pill */
.stage-top .tipbox-float{
  position:absolute;top:calc(100% + 8px);left:0;max-width:min(280px,100%);margin:0;pointer-events:auto;
  background:color-mix(in srgb,var(--paper-2) 90%,transparent);
  -webkit-backdrop-filter:saturate(180%) blur(14px);backdrop-filter:saturate(180%) blur(14px);
  border:1px solid var(--hairline-2);box-shadow:0 8px 22px -14px rgba(18,18,26,.34);
}
input[type=range]{
  -webkit-appearance:none;appearance:none;background:transparent;width:100%;
  height:28px;margin:0;touch-action:pan-y;
}
input[type=range]::-webkit-slider-runnable-track{height:2px;background:var(--hairline-2);border-radius:2px}
input[type=range]::-webkit-slider-thumb{
  -webkit-appearance:none;appearance:none;width:18px;height:18px;border-radius:999px;
  background:var(--ink);margin-top:-8px;border:2px solid var(--paper-2);
  box-shadow:0 1px 4px rgba(0,0,0,.22);transition:transform .14s;
}
input[type=range]:active::-webkit-slider-thumb{transform:scale(1.16)}
input[type=range]::-moz-range-track{height:2px;background:var(--hairline-2);border-radius:2px}
input[type=range]::-moz-range-thumb{
  width:18px;height:18px;border-radius:999px;background:var(--ink);
  border:2px solid var(--paper-2);box-shadow:0 1px 4px rgba(0,0,0,.22);
}
.designs{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:7px}
@media(min-width:420px){.designs{grid-template-columns:repeat(4,minmax(0,1fr))}}
@media(min-width:1000px){.designs{grid-template-columns:repeat(3,minmax(0,1fr))}}
.dchip{
  position:relative;display:flex;flex-direction:column;align-items:center;gap:5px;
  padding:8px 5px;border:1px solid var(--hairline);border-radius:6px;background:var(--paper-2);
  font-size:11px;color:var(--ash);min-height:64px;transition:border-color .18s,color .18s,background .18s;
}
.dchip img{width:32px;height:32px;object-fit:cover;border-radius:4px;background:var(--surface)}
.dchip:hover{border-color:var(--hairline-2);color:var(--ink)}
.dchip[aria-pressed="true"]{border-color:var(--ink);color:var(--ink);background:var(--surface)}
.dchip.locked{opacity:.55}
.dchip .lk{position:absolute;top:4px;right:4px;color:var(--ash-2)}
.shares{margin-top:14px}
.swatches{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:8px}
.sw{
  aspect-ratio:1;border-radius:999px;border:1px solid var(--hairline-2);
  min-height:34px;transition:transform .14s;
}
/* a see-through spool (PLA Translucent): light at the heart, the colour at
   the rim — StudioView.swatch's RadialGradient, white .55 → 0 at (42%, 38%) */
.sw.translucent{position:relative;overflow:hidden}
.sw.translucent::after{content:"";position:absolute;inset:0;border-radius:inherit;
  background:radial-gradient(circle at 42% 38%,rgba(255,255,255,.55) 0%,rgba(255,255,255,0) 44%)}
.spoolcaption{font-size:11px;font-weight:500;color:var(--ash);margin:10px 0 6px}
.spoolcaption:first-child{margin-top:2px}
/* PETG Translucent Clear (32101): no colour — a glass sheen across the disc
   (StudioView.swatch: white 0 → .9 → 0, top-leading to bottom-trailing) */
.sw.clear{position:relative;overflow:hidden}
.sw.clear::before{content:"";position:absolute;inset:0;border-radius:inherit;
  background:linear-gradient(135deg,rgba(255,255,255,0) 20%,rgba(255,255,255,.9) 50%,rgba(255,255,255,0) 80%)}
.sw:hover{transform:scale(1.08)}
.sw[aria-pressed="true"]{box-shadow:0 0 0 2px var(--paper-2),0 0 0 4px var(--ink)}
.pfoot{margin-top:auto;padding:14px 16px 16px;border-top:1px solid var(--hairline);display:flex;flex-direction:column;gap:8px}
.pfoot-status{display:flex;justify-content:space-between;gap:10px;font-size:11px;color:var(--ash-2);min-height:14px}
.pfoot-status span:first-child{color:var(--filament)}
.pfoot .btn{width:100%;min-height:46px}
/* Save beside Download (25 Sep 26): Download keeps the width */
/* My lamps and Save share a row of their own above Download (2 Oct 26), so
   all three keep their words whatever the language */
.pfoot-actions{display:flex;flex-wrap:wrap;gap:8px}
.pfoot-actions .btn{width:auto}
.pfoot-actions #save,.pfoot-actions #lamps{flex:1 1 0;min-width:0;padding-inline:12px}
.pfoot-actions #save span,.pfoot-actions #lamps span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pfoot-actions #export{flex:1 1 100%;min-width:0}
.pfoot-actions .btn svg{flex:0 0 auto}
.lampsbox .savelist{margin-top:0;border-top:0;padding-top:0}
.lampsbox .confirm-actions{margin-top:14px}
.pfoot small{font-size:11.5px;color:var(--ash-2);text-align:center;line-height:1.45}
.growth-media{aspect-ratio:1/1;border-radius:18px;background:var(--surface)}
.growth-media img{width:100%;height:100%;object-fit:cover;display:block}
.growth-slider{width:100%;max-width:34rem;display:flex;flex-direction:column;gap:4px;margin-top:4px}
.growth-slider input[type=range]{height:34px}
.growth-slider .srow-ends{margin-top:-4px}
.feature.timelapse .feature-copy p{color:var(--ash)}
/* ───────────────────────────── steps ───────────────────────────── */
.steps{display:grid;grid-template-columns:1fr;gap:30px;margin-top:40px}
@media(min-width:820px){.steps{grid-template-columns:repeat(3,1fr);gap:40px}}
.step{display:flex;flex-direction:column;gap:9px}
.step .num{font-family:'IBM Plex Mono',ui-monospace,monospace;font-size:11px;color:var(--ash-2);letter-spacing:.12em}
.step h3{font-size:1.1rem;letter-spacing:-.028em}
.step p{font-size:14.5px;color:var(--ash);line-height:1.55}
/* ───────────────────────────── features ───────────────────────────── */
.feature-list{display:flex;flex-direction:column;gap:clamp(48px,8vw,96px)}
.feature{display:flex;flex-direction:column;gap:24px}
.feature-media{margin:0;border-radius:var(--r-card);overflow:hidden;background:var(--surface);aspect-ratio:1/1}
.feature-media.portrait{aspect-ratio:600/1080;max-width:min(100%,400px);margin-inline:auto}
.feature-media.wide{aspect-ratio:1080/600}
.feature-media.growth-media{aspect-ratio:1/1;border-radius:18px}
.feature-media video,.feature-media img{width:100%;height:100%;object-fit:cover}
.feature-copy{display:flex;flex-direction:column;gap:14px;align-items:flex-start}
.feature-copy p{font-size:15px;color:var(--ash);line-height:1.6;max-width:46ch}
@media(min-width:880px){
  .feature{flex-direction:row;align-items:center;gap:56px}
  .feature.reverse{flex-direction:row-reverse}
  .feature-media{flex:1 1 0;min-width:0}
  .feature-copy{flex:1 1 0;min-width:0}
}
/* ───────────────────────────── galleries ───────────────────────────── */
.lamp-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}
@media(min-width:700px){.lamp-grid{grid-template-columns:repeat(3,minmax(0,1fr));gap:14px}}
.lamp-grid figure{margin:0;border-radius:var(--r-control);overflow:hidden;background:var(--surface);aspect-ratio:3/4}
.lamp-grid img{width:100%;height:100%;object-fit:cover;transition:transform .6s cubic-bezier(.2,.7,.3,1)}
.lamp-grid figure:hover img{transform:scale(1.035)}
.piece-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:7px}
@media(min-width:700px){.piece-grid{grid-template-columns:repeat(6,minmax(0,1fr));gap:9px}}
.piece-grid img{width:100%;aspect-ratio:1;object-fit:cover;border-radius:var(--r-control);background:var(--surface)}
/* ───────────────────────────── membership ───────────────────────────── */
.member-list{display:grid;grid-template-columns:1fr;gap:0;border-top:1px solid var(--hairline)}
@media(min-width:760px){.member-list{grid-template-columns:repeat(2,1fr);column-gap:48px}}
.member{padding:20px 0;border-bottom:1px solid var(--hairline)}
.member h4{font-size:15px;font-weight:500;letter-spacing:-.02em;margin-bottom:5px}
.member p{font-size:13.5px;color:var(--ash);line-height:1.55}
/* ───────────────────────────── ddw ───────────────────────────── */
.ddw{display:flex;flex-direction:column;gap:32px}
.ddw-copy{display:flex;flex-direction:column;align-items:flex-start}
.ddw-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:10px}
.ddw-grid img{width:100%;aspect-ratio:1;object-fit:cover;border-radius:var(--r-control);background:var(--surface)}
.ddw-grid img:first-child{grid-column:1 / -1;aspect-ratio:16/10}
@media(min-width:900px){
  .ddw{flex-direction:row;align-items:center;gap:56px}
  .ddw-copy,.ddw-grid{flex:1 1 0;min-width:0}
}
/* ───────────────────────────── pricing ───────────────────────────── */
.price-head{display:flex;flex-direction:column;align-items:center;gap:16px;text-align:center;margin-bottom:36px}
.tiers{display:grid;grid-template-columns:1fr;border:1px solid var(--hairline);border-radius:var(--r-card);overflow:hidden}
@media(min-width:820px){.tiers{grid-template-columns:repeat(3,1fr)}}
.tier{padding:28px 24px;display:flex;flex-direction:column;gap:14px;background:var(--paper-2);border-bottom:1px solid var(--hairline)}
.tier:last-child{border-bottom:none}
@media(min-width:820px){
  .tier{border-bottom:none;border-right:1px solid var(--hairline)}
  .tier:last-child{border-right:none}
}
.tier.feature{background:var(--surface)}
.tier h3{font-size:1.25rem;letter-spacing:-.03em}
.tier .sub{font-size:13.5px;color:var(--ash);line-height:1.5}
.amount{display:flex;align-items:baseline;gap:3px;margin-top:4px}
.amount .cur{font-size:1.3rem;color:var(--ash)}
.amount .n{font-size:2.9rem;letter-spacing:-.05em;font-weight:500;font-variant-numeric:tabular-nums}
.amount .per{font-size:13px;color:var(--ash-2);margin-left:5px}
.billed{font-family:'IBM Plex Mono',ui-monospace,monospace;font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--ash-2)}
.billed .was{text-decoration:line-through;margin-right:8px}
.amount .n .c{font-size:.42em;vertical-align:top;margin-left:.08em}
.tier .offer{font-family:'IBM Plex Mono',ui-monospace,monospace;font-size:10px;letter-spacing:.16em;text-transform:uppercase;color:var(--filament);margin-top:-6px}
.feats{display:flex;flex-direction:column;gap:9px;margin:6px 0 4px}
.feats li{display:grid;grid-template-columns:auto 1fr;gap:9px;font-size:13.5px;color:var(--ash);line-height:1.45}
.feats li::before{content:"–";color:var(--filament)}
.tier .btn{width:100%;margin-top:auto;min-height:46px}
/* ───────────────────────────── faq ───────────────────────────── */
.faq{max-width:820px;margin-top:30px}
.q{border-bottom:1px solid var(--hairline)}
.q:first-child{border-top:1px solid var(--hairline)}
.q summary{
  list-style:none;cursor:pointer;padding:18px 0;
  display:grid;grid-template-columns:1fr auto;gap:16px;align-items:center;
  font-size:15px;letter-spacing:-.015em;
}
.q summary::-webkit-details-marker{display:none}
.q summary .pm{color:var(--ash-2);transition:transform .25s,color .25s;flex:none}
.q[open] summary .pm{transform:rotate(45deg);color:var(--ink)}
.q .a{padding:0 0 20px;font-size:14.5px;color:var(--ash);line-height:1.65;max-width:66ch}
.q .a a{border-bottom:1px solid var(--hairline-2)}
/* ───────────────────────────── touch / closer ───────────────────────────── */
.touch{display:flex;flex-direction:column;gap:24px}
.touch-side{display:flex;flex-direction:column;gap:22px;align-items:flex-start}
@media(min-width:820px){
  .touch{flex-direction:row;align-items:flex-start;justify-content:space-between;gap:56px}
  .touch>div{flex:1 1 0;min-width:0}
}
.closer{display:flex;flex-direction:column;align-items:center;gap:18px;text-align:center}
.closer .lede{text-align:center}
.prose{max-width:64ch;display:flex;flex-direction:column;gap:22px}
.prose p{font-size:clamp(1rem,2.4vw,1.12rem);line-height:1.7;color:var(--ash)}
.prose p:first-child{color:var(--ink)}
/* ───────────────────────────── footer ───────────────────────────── */
footer{border-top:1px solid var(--hairline);padding-block:36px 44px}
.fgrid{display:flex;flex-wrap:wrap;gap:28px 44px;align-items:flex-start}
.fgrid .col{display:flex;flex-direction:column;gap:9px;font-size:13px;color:var(--ash);min-width:120px}
.fgrid .col a:hover{color:var(--ink)}
.fnote{font-size:12px;color:var(--ash-2);line-height:1.6}
.fbot{display:flex;flex-wrap:wrap;gap:8px 20px;justify-content:space-between;margin-top:32px;font-size:12px;color:var(--ash-2)}
/* ───────────────────────────── sheet ───────────────────────────── */
.scrim{
  position:fixed;inset:0;z-index:100;background:var(--scrim);
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
  display:grid;place-items:center;padding:18px;
}
.sheetbox{
  width:100%;max-width:410px;max-height:92vh;overflow-y:auto;
  background:var(--paper);border:1px solid var(--hairline-2);border-radius:var(--r-card);
  padding:24px 22px 20px;display:flex;flex-direction:column;gap:15px;box-shadow:var(--shadow);
}
.sheetbox-head{display:flex;align-items:flex-start;justify-content:space-between;gap:14px}
.sheetbox h3{font-size:1.22rem;letter-spacing:-.032em}
.filecard{display:flex;flex-direction:column;gap:4px;padding:12px 13px;border:1px solid var(--hairline);border-radius:var(--r-control);background:var(--paper-2)}
.filecard .fn{font-size:13.5px;letter-spacing:-.01em}
.filecard .fm{font-family:'IBM Plex Mono',ui-monospace,monospace;font-size:11px;color:var(--ash-2);font-variant-numeric:tabular-nums}
.field{display:flex;flex-direction:column;gap:8px}
.field input{
  min-height:46px;padding:0 13px;border-radius:var(--r-control);border:1px solid var(--hairline-2);
  background:var(--paper-2);color:var(--ink);font:inherit;font-size:16px;width:100%;
}
.field input::placeholder{color:var(--ash-2)}
.field input:focus{outline:none;border-color:var(--ink)}
.err{font-size:12px;color:var(--bad)}
.orline{display:flex;align-items:center;gap:11px;color:var(--ash-2);font-size:11.5px}
.orline::before,.orline::after{content:"";height:1px;background:var(--hairline);flex:1}
.gbtn{
  display:flex;align-items:center;justify-content:center;gap:9px;width:100%;min-height:46px;
  border:1px solid var(--hairline-2);border-radius:999px;font-size:14px;transition:background .18s;
}
.gbtn:hover{background:var(--surface)}
.fine{font-size:11.5px;color:var(--ash-2);text-align:center;line-height:1.5}
.note{font-size:12px;line-height:1.5;color:var(--ash);border-left:2px solid var(--filament);padding-left:11px}
/* the Download sheet (download.js): the bed, the STL switch, the progress */
.dl-what{font-size:12.5px;line-height:1.55;color:var(--ash)}
.dl-row{display:flex;flex-direction:column;gap:8px}
.dl-label{font-family:'IBM Plex Mono',ui-monospace,monospace;font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--ash-2)}
.seg{display:grid;grid-template-columns:repeat(3,1fr);gap:6px}
.seg-btn{
  display:flex;flex-direction:column;align-items:center;gap:2px;padding:9px 6px;border-radius:var(--r-control);
  border:1px solid var(--hairline-2);background:var(--paper-2);color:var(--ink);font:inherit;font-size:12.5px;cursor:pointer;
  transition:background .18s,border-color .18s;
}
.seg-btn small{font-family:'IBM Plex Mono',ui-monospace,monospace;font-size:10px;color:var(--ash-2)}
.seg-btn:hover{background:var(--surface)}
.seg-btn.on{background:var(--ink);color:var(--paper);border-color:var(--ink)}
.seg-btn.on small{color:var(--paper);opacity:.7}
/* the bed pills fit a phone (25 Sep 26): the stage's older .seg button
   rules (no wrap, 13 to 15 px of padding on touch) pushed the H2D pill out
   of the sheet at 390 px; below 375 px the three stack */
.seg{grid-template-columns:repeat(3,minmax(0,1fr))}
.seg .seg-btn{min-width:0;padding:5px 4px;text-align:center}
@media(max-width:374px){
  .seg{grid-template-columns:1fr;border-radius:var(--r-card)}
  .seg .seg-btn{flex-direction:row;justify-content:space-between;align-items:baseline;padding:9px 14px}
}
.dl-switch{display:flex;align-items:center;gap:10px;font-size:13.5px;cursor:pointer;user-select:none}
.dl-switch input{appearance:none;-webkit-appearance:none;width:38px;height:22px;border-radius:999px;background:var(--hairline-2);position:relative;flex:none;cursor:pointer;transition:background .2s;margin:0}
.dl-switch input::after{content:"";position:absolute;top:2px;left:2px;width:18px;height:18px;border-radius:50%;background:var(--paper);box-shadow:0 1px 3px rgba(0,0,0,.25);transition:transform .2s}
.dl-switch input:checked{background:var(--ink)}
.dl-switch input:checked::after{transform:translateX(16px)}
.dl-progress{display:flex;flex-direction:column;gap:7px}
.dl-bar{height:6px;border-radius:999px;background:var(--hairline);overflow:hidden}
.dl-fill{height:100%;width:0;border-radius:999px;background:var(--ink);transition:width .25s ease}
.dl-status{font-family:'IBM Plex Mono',ui-monospace,monospace;font-size:11px;color:var(--ash-2);font-variant-numeric:tabular-nums}
.dl-actions{display:grid;grid-template-columns:1fr 1fr;gap:8px}
/* what downloading accepts (28 Sep 26): small print beside the button */
.dl-licence{font-size:11.5px;line-height:1.5;color:var(--ash)}
.dl-licence a{color:var(--ink);text-decoration:underline;text-underline-offset:2px}
.dl-actions .btn{width:100%}
/* ───────────────────────────── cookies ───────────────────────────── */
.cookie{position:fixed;left:0;right:0;bottom:0;z-index:90;padding:14px;pointer-events:none}
.cookie-in{
  pointer-events:auto;max-width:1180px;margin-inline:auto;
  background:var(--paper-2);border:1px solid var(--hairline-2);border-radius:var(--r-card);
  padding:16px 18px;display:flex;flex-direction:column;gap:14px;box-shadow:var(--shadow);
}
.cookie p{font-size:12.5px;color:var(--ash);line-height:1.55}
.cookie p a{border-bottom:1px solid var(--hairline-2)}
.cookie-act{display:flex;flex-wrap:wrap;gap:8px}
.cookie-act .btn{flex:1 1 auto;min-width:120px}
@media(min-width:820px){
  .cookie-in{flex-direction:row;align-items:center;gap:26px}
  .cookie p{flex:1}
  .cookie-act{flex:none}
  .cookie-act .btn{flex:none;min-width:0}
}
@media(prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms!important;transition-duration:.001ms!important;scroll-behavior:auto!important}
}
/* ───────────────────────────── contact form ───────────────────────────── */
.cform{display:flex;flex-direction:column;gap:16px;margin-top:26px;max-width:34rem}
.cfield{display:flex;flex-direction:column;gap:7px}
.cfield>span{font-family:'IBM Plex Mono',ui-monospace,monospace;font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--ash-2)}
.cfield input,.cfield textarea{
  min-height:46px;padding:12px 13px;border-radius:var(--r-control);border:1px solid var(--hairline-2);
  background:var(--paper-2);color:var(--ink);font:inherit;font-size:16px;width:100%;resize:vertical;
}
.cfield textarea{min-height:130px;line-height:1.55}
.cfield input:focus,.cfield textarea:focus{outline:none;border-color:var(--ink)}
.cform .btn{align-self:flex-start}
.cinfo dl{margin:22px 0 0;display:flex;flex-direction:column;gap:16px}
.cinfo dt{font-family:'IBM Plex Mono',ui-monospace,monospace;font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--ash-2);margin-bottom:4px}
.cinfo dd{margin:0;font-size:14.5px;color:var(--ink);line-height:1.6}
.cinfo dd a{border-bottom:1px solid var(--hairline-2)}
.cinfo dd a:hover{border-color:var(--ink)}
/* ───────────────────── touch targets ─────────────────────
   Text links sit in a 44px-tall hit area on touch without changing how the
   page looks: padding, not size. */
.mark{padding-block:11px}
.nav-links a{padding-block:12px}
.signin{padding-block:12px}
.fgrid .col a{padding-block:6px;margin-block:-2px}
.link-arrow{padding-block:9px 6px}
.cinfo dd a{padding-block:4px;display:inline-block}
@media(hover:none){
  .fgrid .col{gap:4px}
  .fgrid .col a{padding-block:9px}
}
/* ───────── touch sizing: hit areas grow, the design does not ───────── */
.tipbtn{position:relative}
/* 15 px of ink, a 45 px target — the glyph stays small, the thumb does not */
.tipbtn::after{content:"";position:absolute;inset:-15px;border-radius:999px}
input[type=range]{height:34px}
input[type=range]::-webkit-slider-thumb{margin-top:-8px}
@media(hover:none),(pointer:coarse){
  input[type=range]{height:44px}
  input[type=range]::-webkit-slider-thumb{width:22px;height:22px;margin-top:-10px}
  input[type=range]::-moz-range-thumb{width:22px;height:22px}
  .q summary{padding-block:20px}
  .cinfo dd a{padding-block:9px}
  .link-arrow{padding-block:12px 9px}
  .dchip{min-height:74px}
  .sw{min-height:42px}
  .seg button{min-height:36px;padding-inline:15px}
  .tabs button{min-height:52px}
}
/* inline links inside :scope copy get a touch-sized hit area without
   disturbing the line rhythm */
@media(hover:none),(pointer:coarse){
  .q .a a,.cookie p a{padding-block:8px;display:inline-block}
}
/* ───────────────────────────── tray pane ───────────────────────────── */
.tabpane{display:flex;flex-direction:column;gap:2px}
/* ───────────────────────── studio loading state ─────────────────────────
   Visible from first paint so the stage is never a blank box, and removed
   the moment the first lamp is on screen. */
.loading{
  position:absolute;inset:0;display:grid;place-items:center;gap:14px;
  align-content:center;color:var(--ash);pointer-events:none;
  transition:opacity .45s ease;
}
.loading.done{opacity:0}
.loading p{font-size:12.5px;letter-spacing:.01em}
.spinner{
  width:26px;height:26px;border-radius:999px;
  border:1.5px solid var(--hairline-2);border-top-color:var(--filament);
  animation:spin 900ms linear infinite;
}
@media(prefers-reduced-motion:reduce){
  .spinner{animation:none;border-top-color:var(--hairline-2)}
}
/* ───────────── anchor targets clear the sticky nav ─────────────
   Without this, clicking Studio / Pricing / Contact in the nav lands with the
   heading hidden underneath it. */
section[id],main[id],.faq details{scroll-margin-top:78px}
:scope{scroll-behavior:smooth}
@media(prefers-reduced-motion:reduce){html{scroll-behavior:auto}}
/* ───────────── tray fills the stage instead of guessing a height ───────────── */
.panel{min-height:0}
@media(min-width:1000px){
  .tray{flex:1 1 auto;min-height:0;max-height:none;overflow-y:auto;overscroll-behavior:contain}
}
/* ───────────── cookie notice: compact on a phone ─────────────
   Three buttons on one row, not a full-height panel over the page. */
@media(max-width:640px){
  .cookie{padding:10px}
  .cookie-in{padding:13px 14px;gap:11px;border-radius:10px}
  .cookie p{font-size:11.5px;line-height:1.5}
  /* two rows: the two choices side by side, Accept all across the bottom —
     their exact labels, none of them clipped */
  .cookie-act{gap:7px;flex-wrap:wrap}
  .cookie-act .btn{flex:1 1 calc(50% - 4px);min-width:0;font-size:12px;padding-inline:8px;min-height:40px}
  .cookie-act .btn:last-child{flex:1 1 100%}
}
/* ───────────── opened as a file, not served ─────────────
   The Studio needs an origin for WebAssembly and fetch. Say so where the
   lamp would have been, with the exact command to fix it. */
.studio-frame.solo{grid-template-columns:minmax(0,1fr)!important;display:block}
.studio-frame.solo .stage{border-right:none;min-height:340px;position:relative}
.filenote{
  position:absolute;inset:0;display:flex;flex-direction:column;justify-content:center;
  gap:14px;padding:32px;text-align:center;align-items:center;
}
.filenote h3{font-size:1.15rem;letter-spacing:-.03em}
.filenote p{font-size:13.5px;color:var(--ash);line-height:1.6;max-width:44ch}
.filenote-do{color:var(--ink)!important}
.filenote code{
  font-family:'IBM Plex Mono',ui-monospace,monospace;font-size:12.5px;
  background:var(--paper-2);border:1px solid var(--hairline-2);border-radius:5px;
  padding:3px 7px;display:inline-block;margin:3px 1px;user-select:all;
}
/* ═════════════════ Studio tray — Blooms & Colour ═════════════════ */
.tray-head{display:flex;align-items:center;justify-content:space-between;gap:10px;margin:14px 0 8px;
  flex-wrap:wrap;row-gap:8px}
/* a row too narrow for its label and its pills (Repeat's five on a 320 px
   phone, a long word in another language) puts the pills under the label,
   still on the right */
.tray-head > .pills{margin-left:auto}
.tray-label{font-size:12.5px;color:var(--ash);display:inline-flex;align-items:center;gap:6px}
.addbtn{gap:5px;padding-inline:13px}
/* rows: rosette · name · share · % · remove */
.bloomrow{display:grid;grid-template-columns:34px 62px 1fr auto 24px;align-items:center;
  gap:9px;padding:7px 0;border-bottom:1px solid var(--hairline)}
.bloomrow:last-of-type{border-bottom:none}
.rosette{display:block}
.bloomname{font-size:13px;font-weight:500;color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.bloomshare{height:28px}
.bloompct{font-family:'IBM Plex Mono',ui-monospace,monospace;font-size:13px;font-weight:600;
  color:var(--ink);font-variant-numeric:tabular-nums;min-width:40px;text-align:right}
.bloomx{width:24px;height:24px;border-radius:999px;display:grid;place-items:center;
  color:var(--ash);background:var(--surface);transition:color .15s,background .15s}
.bloomx:hover:not(:disabled){color:var(--ink)}
.bloomx:disabled{color:var(--hairline-2);cursor:default}
/* the custom-lamp notice (17 Sep 26): glass, above the dock — here at the
   foot of the stage — sparkle, title, :scope, ✕; slides up, gone in six
   seconds or on a tap */
.notice{position:absolute;left:12px;right:12px;bottom:12px;z-index:6;display:flex;align-items:flex-start;gap:10px;
  padding:12px;border-radius:18px;background:var(--nav-bg);backdrop-filter:saturate(180%) blur(18px);-webkit-backdrop-filter:saturate(180%) blur(18px);
  box-shadow:0 8px 18px rgba(0,0,0,.12),inset 0 1px 0 rgba(255,255,255,.65);cursor:pointer;
  opacity:0;transform:translateY(10px);transition:opacity .35s ease,transform .35s cubic-bezier(.2,.8,.2,1)}
.notice.show{opacity:1;transform:none}
.notice-mark{flex:none;color:var(--filament);margin-top:1px}
.notice-body{display:flex;flex-direction:column;gap:2px;flex:1 1 auto;min-width:0}
.notice-body b{font-size:13px;font-weight:600;color:var(--ink)}
.notice-body span{font-size:12px;line-height:1.4;color:var(--ash)}
.notice-x{flex:none;font-size:11px;font-weight:700;color:var(--ash);margin-top:2px}
@media(min-width:1000px){.notice{left:auto;max-width:360px}}
/* the app's confirmationDialog: Reset to the Starter lamp? */
.confirm{position:fixed;inset:0;z-index:120;background:var(--scrim);display:grid;place-items:center;padding:20px;
  grid-template-columns:minmax(0,1fr);   /* a long saved name ellipsizes instead of widening the sheet past a phone's edge */
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px)}
.confirm-box{width:100%;max-width:340px;background:var(--paper);border-radius:var(--r-card);padding:22px 20px 18px;
  box-shadow:var(--shadow);border:1px solid var(--hairline-2);display:flex;flex-direction:column;gap:8px}
.confirm-box b{font-size:15px;font-weight:600;letter-spacing:-.01em}
.confirm-box p{font-size:13.5px;color:var(--ash);line-height:1.45}
.confirm-actions{display:flex;gap:8px;margin-top:10px}
.confirm-actions .btn{flex:1 1 0}
/* Save this lamp: the name, and the lamps saved so far (25 Sep 26) */
.savebox{max-width:380px}
.savename{width:100%;min-height:44px;padding:0 14px;border-radius:12px;border:1px solid var(--hairline-2);
  background:var(--surface);color:var(--ink);font:inherit;font-size:15px}
.savename:focus{outline:2px solid var(--ink);outline-offset:1px}
.savelist:empty{display:none}
.savelist{display:flex;flex-direction:column;margin-top:10px;border-top:1px solid var(--hairline);padding-top:10px;
  max-height:min(40vh,260px);overflow-y:auto}
.savecap{font-size:11.5px;color:var(--ash-2);margin-bottom:4px}
.saverow{display:flex;align-items:center;gap:6px;border-bottom:1px solid var(--hairline)}
.saverow:last-child{border-bottom:0}
.saveopen{flex:1 1 auto;min-width:0;display:flex;align-items:center;gap:12px;
  padding:8px 2px;text-align:left;cursor:pointer;color:var(--ink)}
/* the lamp's picture (2 Oct 26), a square beside its name */
.savethumb{flex:0 0 auto;width:46px;height:46px;border-radius:10px;overflow:hidden;background:var(--surface);display:block}
.savethumb img{display:block;width:100%;height:100%;object-fit:cover}
.savethumb-none{background:var(--surface)}
.savewords{flex:1 1 auto;min-width:0;display:flex;justify-content:space-between;align-items:baseline;gap:10px}
.saveopen:hover .savenm{text-decoration:underline}
.savenm{font-size:13.5px;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.savedt{font-size:11.5px;color:var(--ash-2);white-space:nowrap}
.savedel{flex:0 0 auto;min-width:40px;min-height:40px;display:grid;place-items:center;border-radius:999px;color:var(--ash);cursor:pointer}
.savedel svg{width:18px;height:18px}
.savedel:hover{background:var(--surface);color:var(--ink)}
.savedel.arm{padding:0 12px;background:var(--ink);color:var(--paper);font-size:12px}
/* where the lamps are kept (27 Sep 26): this browser, with a way to sign in, or the account */
.savenote{margin:-4px 0 2px;font-size:12px;line-height:1.5;color:var(--ash)}
.savenote[hidden]{display:none}
/* on a desktop the sheets are roomier and their words larger (owner, 2 Oct
   26: "the window is a bit tiny for web the texts are small here") */
@media (min-width:760px) and (pointer:fine){
  .savebox{max-width:500px;padding:28px 28px 24px;gap:10px}
  .savebox b{font-size:19px}
  .savenote{font-size:14px;margin-top:-2px}
  .savename{min-height:50px;font-size:16px}
  .savelist{max-height:min(50vh,360px)}
  .savecap{font-size:12.5px}
  .saveopen{padding:9px 4px}
  .savethumb{width:60px;height:60px;border-radius:12px}
  .savenm{font-size:16px}
  .savedt{font-size:13.5px}
  .savedel{min-width:44px;min-height:44px}
  .savedel svg{width:22px;height:22px}
  .savebox .confirm-actions .btn{min-height:48px;font-size:15px}
  .lampsbox [data-testid="lamps-empty"]{font-size:14px}
}
.savelink{display:inline;padding:0;border:0;background:none;font:inherit;color:var(--ink);text-decoration:underline;text-underline-offset:2px;cursor:pointer}
.savelink:hover{text-decoration:none}
@media(hover:none),(pointer:coarse){.savelink{padding-block:8px}}
/* the savedAs toast — above the sheets */
.toast{position:fixed;left:50%;bottom:22px;transform:translateX(-50%) translateY(6px);z-index:130;
  max-width:min(92vw,520px);background:var(--ink);color:var(--paper);padding:11px 18px;border-radius:999px;
  font-size:13.5px;line-height:1.35;text-align:center;box-shadow:var(--shadow);opacity:0;pointer-events:none;
  transition:opacity .25s ease,transform .25s ease}
.toast.show{opacity:1;transform:translateX(-50%) translateY(0)}
/* the Add sheet */
.browser{position:fixed;inset:0;z-index:110;background:var(--scrim);
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);display:grid;place-items:end center;padding:0}
@media(min-width:760px){.browser{place-items:center;padding:24px}}
/* min-width:0 — the box is a grid item, and without it the sketch's 26-chip
   "Start from" strip (a scroller) set the box's minimum width to the strip's
   full length: on a phone the sheet grew past the screen and its right edge
   was cut off. */
.browser-box{width:100%;max-width:560px;max-height:86vh;display:flex;flex-direction:column;gap:12px;min-width:0;
  background:var(--paper);border:1px solid var(--hairline-2);
  border-radius:var(--r-card) var(--r-card) 0 0;padding:18px 18px 22px;box-shadow:var(--shadow)}
@media(min-width:760px){.browser-box{border-radius:var(--r-card)}}
.browser-head{display:flex;align-items:center;justify-content:space-between}
.browser-head strong{font-size:1.05rem;letter-spacing:-.03em;font-weight:500}
.browser-search{display:flex;align-items:center;gap:9px;padding:0 14px;min-height:42px;
  background:var(--surface);border-radius:999px;color:var(--ash)}
.browser-search input{flex:1;border:none;background:none;font:inherit;font-size:15px;color:var(--ink);
  min-width:0;outline:none;-webkit-appearance:none}
.browser-hint{font-size:12.5px;color:var(--bad)}
.browser-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(88px,1fr));gap:10px;
  overflow-y:auto;padding-bottom:4px;overscroll-behavior:contain}
.bcell{display:flex;flex-direction:column;align-items:center;gap:5px;padding:4px 2px 8px}
.bdisc{position:relative;display:grid;place-items:center;padding:8px;border-radius:999px;
  background:var(--paper-2);box-shadow:inset 0 0 0 .8px var(--hairline);transition:box-shadow .15s}
.bcell.on .bdisc{box-shadow:inset 0 0 0 2px var(--ink)}
.bcell.just-saved .bdisc{animation:justsaved 1.6s ease-out 1}
.btick{position:absolute;top:-2px;right:-2px;color:var(--ink);background:#fff;border-radius:999px}
.bname{font-size:12px;font-weight:500;color:var(--ink);text-align:center;line-height:1.25}
.bcluster{font-size:8px;font-weight:700;letter-spacing:.08em;color:var(--filament)}
/* colour styles */
/* The app scrolls these sideways because an iOS tray is short. A web tray
   already scrolls vertically, so they wrap instead: a colour style or palette
   sitting half-off the edge is a control the viewer never finds. */
.chiprow{display:flex;flex-wrap:wrap;gap:8px;padding:2px 0 6px}
/* ColorSection.modeChip: an ink-filled capsule when active, a 6 % ink well
   when not — no outline in either state, which is what the app draws. */
.modechip{flex:0 0 auto;display:inline-flex;align-items:center;gap:7px;min-height:38px;
  padding:0 16px;border-radius:999px;border:0;background:color-mix(in srgb,var(--ink) 6%,transparent);
  font-size:14px;font-weight:500;color:var(--ink);white-space:nowrap;
  transition:color .15s,background .15s}
.modechip.on{color:var(--paper-2);background:var(--ink)}
.modechip.on .chipdot{box-shadow:0 0 0 1.2px var(--ink)}
/* ColorSection (23 Sep 26). The plastic: PLA / PETG pills beside the
   "Material" label, and one line under them saying what mixes. */
.materialrow{margin-top:6px}
.materialnote{margin:-2px 0 12px}
/* The STYLE — the parent: four big tiles in one row, the colours on top and
   the name under them, ink-filled when chosen (styleTile: 18 pt dots over a
   13 pt semibold name on a 14 pt-radius tile). */
.styletiles{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:8px;margin:2px 0 10px}
.styletile{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:7px;
  min-height:62px;padding:10px 4px;border:0;border-radius:14px;
  background:color-mix(in srgb,var(--ink) 6%,transparent);color:var(--ink);
  transition:color .15s,background .15s}
.styletile.on{background:var(--ink);color:var(--paper-2)}
.tilename{font-size:13px;font-weight:600;line-height:1.15;text-align:center;overflow-wrap:anywhere}
.tiledots{display:inline-flex}
.tiledots .chipdot{width:18px;height:18px;margin-right:-5px;box-shadow:0 0 0 1.2px #fff}
.tiledots .chipdot:last-child{margin-right:0}
/* Its PRESETS — the children: a tinted panel under the tiles with a small
   caption and small outlined chips, never the size or style of a tile
   (presetPanel: ink 4 %, radius 12; presetChip: 28 pt, 10 pt dots, 12 pt
   text; chosen = an ink outline on the surface). They wrap on the web: a
   chip half off the edge is a control nobody finds. */
.presetpanel{display:flex;flex-direction:column;gap:6px;margin:0 0 10px;padding:8px 10px;
  border-radius:12px;background:color-mix(in srgb,var(--ink) 4%,transparent)}
.presetcap{font-size:11px;font-weight:500;color:var(--ash)}
.presetrow{display:flex;flex-wrap:wrap;gap:6px}
.presetchip{display:inline-flex;align-items:center;gap:5px;height:28px;padding:0 10px;border-radius:999px;
  background:transparent;border:.8px solid var(--hairline-2);color:var(--ink);font-size:12px;white-space:nowrap}
.presetchip .chipdot{width:10px;height:10px;margin-right:-3px;box-shadow:0 0 0 .8px #fff}
.presetchip .chipdot:last-child{margin-right:0}
.presetchip.on{background:var(--surface);border:1.4px solid var(--ink);font-weight:600}
@media(hover:none),(pointer:coarse){.presetchip{height:34px}}
/* LeoraSlider, sideways only: the box listens, the range only draws */
.sway{display:block;position:relative;min-width:0;touch-action:pan-y;cursor:pointer}
.sway>input[type=range]{pointer-events:none;display:block;width:100%}
.sway.dragging>input[type=range]::-webkit-slider-thumb{transform:scale(1.16)}
/* the preset sub-row under Stripes / Organic: indented behind a hairline,
   labelled, and its chips a size down — outlined when chosen, so a chosen
   palette never looks like a second chosen style */
.subrow{
  display:flex;flex-direction:column;gap:6px;
  margin:2px 0 6px 10px;padding-left:12px;border-left:2px solid var(--hairline-2);
}
.sublabel{
  font-family:'IBM Plex Mono',ui-monospace,monospace;font-size:10px;
  letter-spacing:.14em;text-transform:uppercase;color:var(--ash-2);
}
.subrow .chiprow{padding:0}
.modechip.sub{min-height:32px;padding:0 12px;font-size:13px;gap:6px;
  background:transparent;border:1px solid var(--hairline-2);color:var(--ash)}
.modechip.sub .chipdot{width:9px;height:9px}
.modechip.sub.on{background:transparent;border-color:var(--ink);color:var(--ink);font-weight:600}
.modechip.sub.on .chipdot{box-shadow:0 0 0 1.2px var(--paper-2)}
.chipdots{display:inline-flex}
.chipdot{width:11px;height:11px;border-radius:999px;margin-right:-4px;
  box-shadow:0 0 0 1.2px var(--paper-2)}
.chipdot:last-child{margin-right:0}
.spoolrow{display:grid;grid-template-columns:15px 1fr auto;align-items:center;gap:10px;width:100%;
  padding:9px 0;border-bottom:1px solid var(--hairline);text-align:left}
.spoolrow:last-of-type{border-bottom:none}
.spoolrow{grid-template-columns:15px 1fr auto auto}
.spoolrow .chev{font-size:10px;color:var(--ash-2);margin-left:6px}
.spoolrow.open .chev{color:var(--ink)}
.linkbtn{align-self:flex-start;padding:6px 0;font-size:12.5px;color:var(--filament)}
.linkbtn:hover{text-decoration:underline}
.spooldot{width:15px;height:15px;border-radius:999px;box-shadow:inset 0 0 0 .8px var(--hairline)}
.spoolname{font-size:13px;font-weight:500;color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.spoolval{font-size:11.5px;color:var(--ash)}
button.spoolrow{cursor:pointer}
button.spoolrow:hover .spoolname{color:var(--filament)}
.pills{display:inline-flex;padding:2px;gap:2px;border:1px solid var(--hairline-2);
  border-radius:999px;background:var(--paper-2)}
.pills button{min-height:30px;padding:0 11px;border-radius:999px;font-size:12px;color:var(--ash);
  transition:background .15s,color .15s;white-space:nowrap}
.pills button[aria-pressed="true"]{background:var(--ink);color:var(--paper)}
@media(hover:none),(pointer:coarse){
  .pills button{min-height:36px;padding:0 13px}
  .bloomx{width:30px;height:30px}
}
/* ───────────────────────── sketch a bloom (DrawView) ───────────────────────── */
.sk-open{
  display:flex;align-items:center;justify-content:center;gap:8px;width:100%;
  margin-top:12px;padding:11px 0;border-radius:999px;border:1.1px solid var(--ink);
  font-size:14px;font-weight:500;color:var(--ink);
}
.sk-open:hover{background:var(--surface)}
.bedit{
  position:absolute;left:-2px;top:-2px;width:22px;height:22px;border-radius:999px;
  background:var(--paper-2);border:1px solid var(--hairline-2);font-size:12px;color:var(--ink);
  display:grid;place-items:center;
}
/* The sheet is capped at 86vh; the BODY scrolls inside it (the header with
   Done stays put), as the Add sheet's grid does. Without this the sketch's
   controls ran on past the box and were cut off by the window — Cluster,
   Spiral seam, the rim sliders, Save and Use in Studio were unreachable on
   any screen shorter than the sheet. */
.sketch-box{max-width:560px;overflow:hidden}
.sketch-body{display:flex;flex-direction:column;gap:14px;padding:4px 2px 2px 0;
  flex:1 1 auto;min-height:0;overflow-y:auto;overscroll-behavior:contain}
.sk-section{display:flex;flex-direction:column;gap:8px}
.sk-strip{display:flex;gap:8px;overflow-x:auto;min-width:0;padding:2px 2px 6px;scrollbar-width:none}
.sk-strip::-webkit-scrollbar{display:none}
.sk-start{flex:none;width:58px;display:flex;flex-direction:column;align-items:center;gap:3px}
.sk-disc{width:46px;height:46px;border-radius:999px;background:var(--paper-2);display:grid;place-items:center;
  border:.8px solid var(--hairline);overflow:hidden}
.sk-start.on .sk-disc{border:2px solid var(--ink)}
.sk-blank{width:30px;height:30px;border-radius:999px;border:1px dashed var(--ash)}
.sk-name{font-size:9px;font-weight:500;color:var(--ash);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:58px}
.sk-row{display:grid;grid-template-columns:1fr 138px;gap:8px}
.sk-canvas{width:100%;height:250px;border-radius:var(--r-card);background:var(--paper-2);box-shadow:0 10px 44px rgba(0,0,0,.06);display:block;touch-action:none}
.sk-side{height:250px;border-radius:var(--r-card);background:var(--surface);box-shadow:0 10px 44px rgba(0,0,0,.06);
  display:flex;flex-direction:column;overflow:hidden}
.sk-preview{width:138px;height:138px;flex:1 1 auto;object-fit:contain;display:block;cursor:grab;touch-action:none}
.sk-monthrow{display:flex;align-items:center;gap:4px;padding:0 8px 6px}
.sk-monthlabel{font-size:10px;font-weight:600;font-variant-numeric:tabular-nums;color:var(--ink);white-space:nowrap}
.sk-month{flex:1 1 auto;min-width:0}
.sk-month .srow-head{display:none}
.sk-hint{font-size:12px;color:var(--ash);margin-top:-6px}
.sk-readout{border-top:none;padding:0}
.sk-readout .tile.warn b{color:var(--bad)}
.sk-swatches .sw{width:26px;height:26px;min-height:26px}
/* .sw's 34px floor made these ovals */
.sk-actions{display:flex;gap:8px}
.sk-actions .btn{flex:1 1 0}
.sk-canvaspick{align-self:flex-start}
@media(max-width:560px){
  .sk-row{grid-template-columns:1fr}
  .sk-side{height:auto;flex-direction:row;align-items:center}
  .sk-preview{width:138px;height:138px;flex:none}
  .sk-monthrow{flex:1;padding:0 12px 0 4px}
}
/* ── the wide-screen Studio: one rounded stage card, the controls floating
   over it. LAST in the file on purpose — these override the base .stage and
   .panel rules above, which a media query does not out-specify. ── */
@media(min-width:1000px){
  /* A fixed frame height, not a max: a block sized "auto" grows to its
     content whatever max-height says, so a long Colour tray pushed the
     Download button out of the frame. With the height pinned, the tray is
     the only thing that scrolls. */
  .studio-frame{display:block;position:relative;gap:0;height:min(78vh,740px);min-height:560px}
  .stage{position:absolute;inset:0}
  .panel{
    position:absolute;z-index:4;
    top:var(--panel-gap);right:var(--panel-gap);bottom:var(--panel-gap);width:var(--panel-w);
    border-radius:26px;border:1px solid var(--hairline-2);
    background:color-mix(in srgb,var(--paper-2) 88%,transparent);
    -webkit-backdrop-filter:saturate(180%) blur(20px);backdrop-filter:saturate(180%) blur(20px);
    box-shadow:0 30px 60px -28px rgba(18,18,26,.42);
  }
  /* the stats float over the lamp too, bottom-left, as a glass pill */
  .readout{
    position:absolute;left:12px;bottom:12px;z-index:3;
    display:inline-flex;align-items:baseline;gap:4px 16px;
    padding:9px 15px;border-top:none;border-radius:999px;border:1px solid var(--hairline-2);
    background:color-mix(in srgb,var(--paper-2) 78%,transparent);
    -webkit-backdrop-filter:saturate(180%) blur(14px);backdrop-filter:saturate(180%) blur(14px);
    box-shadow:0 8px 22px -14px rgba(18,18,26,.34);
  }
  /* the overlays keep clear of the floating panel */
  .stage-top{right:calc(var(--panel-w) + var(--panel-gap) + 56px)}
  .stage-zoom{right:calc(var(--panel-w) + var(--panel-gap) + 12px)}
  .herohint{left:calc(50% - (var(--panel-w) + var(--panel-gap)) / 2)}
}

:scope{background:transparent;overflow:visible;
  font-family:var(--font-geist-sans),ui-sans-serif,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif}
.mono,.readout{font-family:var(--font-geist-mono),ui-monospace,SFMono-Regular,Menlo,monospace}
:scope[data-theme="dark"]{
  --paper:#0E0A14; --paper-2:#151020; --surface:#1B1527;
  --bone:#221B2E; --bone-dim:#2A2238;
  --viewport:#130E1C; --viewport-2:#0E0A14;
  --sweep-top:#171221; --sweep-bot:#0B0810;
  --hairline:rgba(255,255,255,.10); --hairline-2:rgba(255,255,255,.19);
  --nav-bg:rgba(14,10,20,.80); --scrim:rgba(4,2,8,.72);
  --shadow:0 24px 60px -24px rgba(0,0,0,.8);
}
/* the shadow belongs to the cards, not to the frame that holds them */
.stage{box-shadow:var(--shadow)}

}
