/* Bangr Mobile — dark, thumb-friendly, iOS safe areas respected.
   The palette and type are lifted from the desktop app so the two read as one
   product. Only the layout differs, because a phone is not a sidebar. */

/* Self-hosted rather than pulled from Google's CDN like the desktop app does.
   That is fine for a tool that runs on a desk with a connection; this one has
   to keep its typeface with no signal, which is the whole premise. Each family
   is a variable font, so one file covers every weight — 148 KB for all three. */
@font-face{font-family:'Sora';font-style:normal;font-weight:200 700;
  font-display:swap;src:url('fonts/sora.woff2') format('woff2')}
@font-face{font-family:'Hanken Grotesk';font-style:normal;font-weight:400 700;
  font-display:swap;src:url('fonts/hanken-400.woff2') format('woff2')}
@font-face{font-family:'JetBrains Mono';font-style:normal;font-weight:500 700;
  font-display:swap;src:url('fonts/jetbrains-500.woff2') format('woff2')}

:root{
  /* ORBIT — a cinematic night. The screen is weather; the post floats in it. */
  --bg:#07090e; --bg2:#0b0e15; --panel:#11151d; --panel2:#161b25;
  --line:#1e2532; --line2:#2b3444;
  --ink:#eef2f7; --dim:#9aa5b4; --faint:#6f7b8b;
  --ember3:#a9c8ff;
  --molten:linear-gradient(135deg,#ff5e15 0%,#ff8a2b 48%,#ffb347 100%);
  --glow:0 0 0 1px rgba(255,255,255,.06), 0 18px 46px -18px rgba(0,0,0,.9);
  --go:#5fd39a; --err:#ff6b6b;
  --radius:16px; --radius-sm:11px;
  --font-display:'Sora',system-ui,sans-serif;
  --font-body:'Hanken Grotesk',system-ui,sans-serif;
  --font-mono:'JetBrains Mono',ui-monospace,Menlo,Consolas,monospace;
  --ember:#ff6a1a; --ember2:#ff9d2f;
  --ember-lo:#ff5e15; --ember-em:#ff8a2b;
  --ember-hi:#ffb347; --ember-cta:#ff8a2b;
  --on-ember:#0a0c10;
  --sky1:#2b3f57; --sky2:#0d1017;
  --halo-a:rgba(120,190,255,.17); --halo-b:rgba(255,150,90,.14);
  --tabbg:rgba(7,9,14,.86);
  --safe-t:env(safe-area-inset-top,0px);
  --safe-b:env(safe-area-inset-bottom,0px);
  --tabh:64px;
}
/* ---------- colour themes ----------
   :root above is the default (ember). Each block swaps the accent ramp AND
   retints the greys: the warm darks are half the app's character, so a cool
   accent dropped onto them looks muddy. The home-screen icon is a fixed brand
   asset from the desktop app and is deliberately never themed. */
[data-theme="violet"]{
  --sky1:#3a2f63; --sky2:#0d0b16; --halo-a:rgba(150,120,255,.20); --halo-b:rgba(255,120,200,.13);
  --ember:#8d7bff; --ember2:#a996ff; --ember-lo:#8d7bff; --ember-em:#8d7bff;
  --ember-hi:#a996ff; --ember-cta:#a996ff; --molten:linear-gradient(135deg,#8d7bff,#a996ff);
}
[data-theme="magenta"]{
  --sky1:#5a2740; --sky2:#150a11; --halo-a:rgba(255,90,150,.20); --halo-b:rgba(255,170,110,.13);
  --ember:#ff3b7f; --ember2:#ff6f9f; --ember-lo:#ff3b7f; --ember-em:#ff3b7f;
  --ember-hi:#ff6f9f; --ember-cta:#ff6f9f; --molten:linear-gradient(135deg,#ff3b7f,#ff6f9f);
}
[data-theme="cyan"]{
  --sky1:#1d4657; --sky2:#08131a; --halo-a:rgba(90,210,255,.20); --halo-b:rgba(120,255,220,.12);
  --ember:#00c2ff; --ember2:#5ad6ff; --ember-lo:#00c2ff; --ember-em:#00c2ff;
  --ember-hi:#5ad6ff; --ember-cta:#5ad6ff; --molten:linear-gradient(135deg,#00c2ff,#5ad6ff);
}
[data-theme="lime"]{
  --sky1:#31481f; --sky2:#0a1108; --halo-a:rgba(180,255,90,.18); --halo-b:rgba(255,230,120,.12);
  --ember:#a8e02a; --ember2:#c6f05c; --ember-lo:#a8e02a; --ember-em:#a8e02a;
  --ember-hi:#c6f05c; --ember-cta:#c6f05c; --molten:linear-gradient(135deg,#a8e02a,#c6f05c);
}
[data-theme="gold"]{
  --sky1:#5a4a1c; --sky2:#14100a; --halo-a:rgba(255,215,90,.20); --halo-b:rgba(255,140,60,.13);
  --ember:#f2c024; --ember2:#ffd95c; --ember-lo:#f2c024; --ember-em:#f2c024;
  --ember-hi:#ffd95c; --ember-cta:#ffd95c; --molten:linear-gradient(135deg,#f2c024,#ffd95c);
}

/* ---------- the startup colour picker ---------- */
.pick{
  position:fixed;inset:0;z-index:90;background:var(--bg);overflow-y:auto;
  padding:calc(var(--safe-t) + 30px) 20px calc(var(--safe-b) + 22px);
}
.pick h2{font-family:var(--font-display);font-size:26px;font-weight:800;
  letter-spacing:-.9px;line-height:1.15}
.pick .psub{color:var(--dim);font-size:13.5px;margin-top:8px;line-height:1.45}
.pick-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:20px}
.pick-tile{
  background:var(--panel);border:1.5px solid var(--line2);border-radius:16px;
  padding:12px;display:flex;flex-direction:column;gap:9px;
  color:var(--ink);font:inherit;text-align:left;cursor:pointer;
}
.pick-tile.on{border-color:var(--ember);box-shadow:inset 0 0 0 1.5px var(--ember)}
.pick-chip{height:46px;border-radius:11px;display:grid;place-items:center}
.pick-chip span{font-size:11px;font-weight:800;letter-spacing:.4px}
.pick-name{font-size:13px;font-weight:700}

*{margin:0;padding:0;box-sizing:border-box;-webkit-tap-highlight-color:transparent}
/* a class that sets display would otherwise beat the hidden attribute */
[hidden]{display:none !important}
html,body{height:100%}
body{
  background:var(--bg); color:var(--ink);
  font:15px/1.45 var(--font-body);
  overscroll-behavior-y:none;
}
.app{height:100%}

/* ---------- screens ---------- */
.screen{
  position:fixed; inset:0; display:none; flex-direction:column;
  padding-top:var(--safe-t);
  padding-bottom:calc(var(--tabh) + var(--safe-b));
}
.screen.show{display:flex}
.hdr{padding:22px 20px 8px}
/* The brand lockup, matching the desktop app: icon, wordmark, and a spaced
   caps line beneath. Read together it says Bangr Mobile, which is why the
   wordmark alone stays "Bangr" — stacking the qualifier is what makes it a
   lockup rather than a long title. */
.brand{display:flex;align-items:center;gap:11px;margin-bottom:16px}
/* The real icon, straight from the desktop app. Using the asset rather than a
   CSS approximation means it cannot drift from the icon on the home screen,
   and it stays itself whatever accent the user picked — a logo that recolours
   with the theme is not a logo. The radius is ours: the PNG is a full-bleed
   square because iOS masks it, so in-app we round it to match. */
/* bangr-mark-*.png, straight from the logo spec: the rounding is baked into
   the alpha at 11/38 of the size. The CSS radius repeats that exact ratio so
   the glow traces the same silhouette — box-shadow follows the border box,
   not the alpha, and a square glow behind a rounded mark is the giveaway. */
.mark{width:38px;height:38px;border-radius:28.9%;display:block;flex:none;
  box-shadow:var(--glow)}
.blockup{display:flex;flex-direction:column;min-width:0}
.bname{font-family:var(--font-display);font-weight:800;font-size:19px;
  letter-spacing:-.5px;line-height:1;color:var(--ink)}
/* Part of the lockup, so it is pinned to the spec's colour rather than the
   theme — the strapline travels with the logo, not with the interface. */
.btag{
  font-family:var(--font-mono);font-size:9.5px;letter-spacing:1.5px;
  text-transform:uppercase;color:#ff8c3c;margin-top:3px;white-space:nowrap;
}
.brand.big{gap:13px;margin-bottom:24px}
.brand.big .mark{width:54px;height:54px}
.brand.big .bname{font-size:26px;letter-spacing:-.7px}
.brand.big .btag{font-size:11px;letter-spacing:1.8px}
.hdr h1{font-family:var(--font-display);font-size:24px;font-weight:800;letter-spacing:-.6px}
.hl{font-family:var(--font-display);font-size:30px;font-weight:800;
  letter-spacing:-1px;line-height:1.02}
.em{background:linear-gradient(135deg,var(--ember-em),var(--ember-hi));
  -webkit-background-clip:text;background-clip:text;color:transparent}
.tag{color:var(--dim);font-size:13.5px;margin-top:7px;line-height:1.45}
.body{flex:1;overflow-y:auto;-webkit-overflow-scrolling:touch;padding:10px 20px 28px}

/* ---------- inputs ---------- */
.lab{display:block;font-family:var(--font-mono);font-size:10px;letter-spacing:1.6px;
  text-transform:uppercase;color:var(--faint);margin:18px 0 7px;font-weight:500}
.lab b{color:var(--ember2);float:right;letter-spacing:0;text-transform:none;font-size:12px}
input[type=text],textarea{
  width:100%;background:var(--panel);border:1.5px solid var(--line2);border-radius:13px;
  padding:13px 14px;color:var(--ink);font:inherit;font-size:16px;
}
textarea{resize:none;line-height:1.45}
input[type=text]:focus,textarea:focus{outline:none;border-color:var(--ember)}
.two{display:grid;grid-template-columns:1fr 1fr;gap:12px}
input[type=range]{
  width:100%;height:34px;background:transparent;-webkit-appearance:none;
}
input[type=range]::-webkit-slider-runnable-track{height:5px;border-radius:3px;background:var(--line2)}
input[type=range]::-webkit-slider-thumb{
  -webkit-appearance:none;width:26px;height:26px;border-radius:50%;
  background:var(--ember);margin-top:-11px;box-shadow:0 2px 8px rgba(0,0,0,.5);
}

/* ---------- file pickers ---------- */
/* A row rather than a stacked drop-zone: the same information in roughly half
   the height, which is what buys the preview a foothold on screen before you
   have scrolled anywhere. */
.picker{
  width:100%;background:var(--panel);border:1.6px dashed var(--line2);
  border-radius:16px;padding:13px 16px;color:var(--ink);cursor:pointer;
  display:grid;grid-template-columns:auto 1fr;column-gap:12px;
  align-items:center;text-align:left;
}
/* the avatar picker carries no glyph, so it keeps the centred stack */
.picker.small{
  display:flex;flex-direction:column;align-items:center;gap:3px;
  padding:12px;border-style:solid;margin-top:14px;text-align:center;
}
.picker.has{border-color:var(--ember);border-style:solid;background:rgba(255,106,26,.07)}
.pico{grid-row:1 / span 2;font-size:24px;color:var(--ember2);line-height:1}
.pt{font-weight:650;font-size:15px}
.ps{font-size:12px;color:var(--faint)}

/* ---------- preview ---------- */
/* A remove control only appears once something is loaded. Understated on
   purpose — it sits under a picker you have already used, so it needs to be
   findable, not loud. */
.picker-clear{
  display:block;margin:8px auto 0;padding:6px 10px;
  background:transparent;border:0;color:var(--faint);
  font:inherit;font-size:12.5px;font-weight:600;cursor:pointer;
  text-decoration:underline;text-underline-offset:3px;
}
.picker-clear:active{color:var(--ink)}

/* Sits directly under Caption size, so every control that changes how the card
   looks is above it and you scroll down to the result. It is a plain block on
   purpose: pinning it to the top fought the keyboard for the same space and
   the keyboard has to win. */
.stage-card{
  position:relative;margin-top:14px;background:#000;border-radius:16px;
  overflow:hidden;border:1px solid var(--line);display:grid;place-items:center;
}
.stage-card canvas,.stage-card video{width:100%;display:block;max-height:46vh;object-fit:contain}

/* The frame source for video posts. iOS only decodes what it renders, so this
   is mounted full-size inside the preview card rather than hidden away — the
   canvas sits on top of it and is opaque, which hides it completely without
   ever telling the browser not to draw it. */
.frame-source{
  position:absolute;inset:0;width:100%;height:100%;
  object-fit:contain;pointer-events:none;z-index:0;
}
/* object-fit letterboxes the bitmap inside the element box, and those bars are
   transparent — which let the frame source behind show through at the edges.
   An opaque background on the canvas itself closes the gap while still leaving
   the video painted underneath, which is all iOS asks for. */
.stage-card > canvas{position:relative;z-index:1;background:#000}



/* ---------- segmented ---------- */
.seg{display:flex;background:var(--panel);border:1.5px solid var(--line2);
  border-radius:13px;overflow:hidden}
.seg button{
  flex:1;padding:13px 6px;background:transparent;border:0;color:var(--dim);
  font:inherit;font-size:13.5px;font-weight:600;cursor:pointer;
  border-right:1px solid var(--line);
}
.seg button:last-child{border-right:0}
.seg button.on{background:var(--panel2);color:var(--ink);box-shadow:inset 0 0 0 1.5px var(--ember)}

/* ---------- rows & switches ---------- */
.row{display:flex;align-items:center;justify-content:space-between;gap:14px;
  padding:15px 0;border-bottom:1px solid var(--line)}
.rl{font-weight:600;font-size:14.5px}
.rl em{display:block;font-style:normal;font-weight:400;font-size:12px;color:var(--faint);margin-top:2px}
.sw{position:relative;width:52px;height:31px;flex:none}
.sw input{display:none}
.sw i{position:absolute;inset:0;border-radius:31px;background:var(--line2);transition:.18s}
.sw i:after{content:"";position:absolute;width:27px;height:27px;border-radius:50%;
  background:#fff;top:2px;left:2px;transition:.18s}
.sw input:checked + i{background:var(--ember)}
.sw input:checked + i:after{transform:translateX(21px)}

/* ---------- swatches ---------- */
.swatches{display:flex;gap:9px;flex-wrap:wrap}
.swatches button{width:34px;height:34px;border-radius:9px;border:2px solid var(--line2);cursor:pointer}
.swatches button.on{border-color:#fff;transform:scale(1.08)}

/* ---------- buttons ---------- */
.cta{
  width:100%;margin-top:24px;padding:17px;border:0;border-radius:15px;
  background:var(--molten);
  color:var(--on-ember);font-family:var(--font-display);font-size:16.5px;
  font-weight:800;letter-spacing:-.3px;cursor:pointer;
}
.cta:disabled{opacity:.5}
.ghost{
  width:100%;margin-top:10px;padding:15px;border:1.5px solid var(--line2);
  border-radius:14px;background:transparent;color:var(--ink);font:inherit;
  font-size:15px;font-weight:600;cursor:pointer;
}
.note{color:var(--faint);font-size:12.5px;margin-top:10px;text-align:center}

/* ---------- tabs ---------- */
.tabs{
  position:fixed;left:0;right:0;bottom:0;z-index:40;
  height:calc(var(--tabh) + var(--safe-b));padding-bottom:var(--safe-b);
  display:flex;background:var(--tabbg);
  backdrop-filter:blur(18px);-webkit-backdrop-filter:blur(18px);
  border-top:1px solid var(--line);
}
.tabs button{
  flex:1;background:transparent;border:0;color:var(--faint);
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;
  font:inherit;font-size:10.5px;font-weight:600;cursor:pointer;
}
.tabs svg{width:23px;height:23px;fill:none;stroke:currentColor;stroke-width:1.9;
  stroke-linecap:round;stroke-linejoin:round}
.tabs button.on{color:var(--ember2)}

/* ---------- result sheet ---------- */
.sheet{position:fixed;inset:0;z-index:60;background:rgba(0,0,0,.6);
  display:flex;align-items:flex-end}
.sheet-in{
  width:100%;max-height:92%;overflow-y:auto;background:var(--panel);
  border-radius:22px 22px 0 0;padding:10px 20px calc(24px + var(--safe-b));
  animation:up .22s ease;
}
@keyframes up{from{transform:translateY(30px);opacity:.6}to{transform:none;opacity:1}}
.grab{width:38px;height:4px;border-radius:3px;background:var(--line2);margin:0 auto 14px}
.sheet-in h2{font-size:20px;font-weight:800;margin-bottom:12px}
/* The finished file is shown here, and on iOS a long press on an image opens
   "Add to Photos" - which saves it without ever touching Save, and so without
   ever passing the ad gate. That is the easy bypass, the one people find by
   accident, and it is worth far more than the airplane-mode one. touch-callout
   suppresses the menu; the Save button beside it is one tap away and is the
   path we actually want people to take. Video controls keep working. */
.result-media video,.result-media img{width:100%;border-radius:14px;background:#000;max-height:52vh;object-fit:contain;
  -webkit-touch-callout:none;-webkit-user-select:none;user-select:none}

/* ---------- busy ---------- */
.busy{position:fixed;inset:0;z-index:70;background:rgba(8,6,5,.9);
  display:grid;place-items:center;backdrop-filter:blur(6px)}
.busy-in{text-align:center;padding:0 32px;width:100%;max-width:340px}
.ring{width:100%;height:6px;border-radius:4px;background:var(--line2);overflow:hidden;margin-bottom:16px}
.ring i{display:block;height:100%;width:0%;background:linear-gradient(90deg,var(--ember),var(--ember-hi));
  transition:width .2s}
.busy-in p{font-weight:650}


/* ---------- ad gate ---------- */
.ad{position:fixed;inset:0;z-index:80;background:rgba(6,5,4,.96);
  display:grid;place-items:center;padding:24px}
.ad-in{width:100%;max-width:360px;text-align:center}
.ad-tag{display:inline-block;font-size:10px;letter-spacing:1.4px;text-transform:uppercase;
  color:var(--faint);border:1px solid var(--line2);border-radius:6px;padding:3px 8px;margin-bottom:18px}
.ad-body{background:var(--panel);border:1px solid var(--line2);border-radius:18px;padding:30px 22px}
.ad-art{width:64px;height:64px;margin:0 auto 16px;border-radius:18px;display:grid;place-items:center;
  background:linear-gradient(135deg,var(--ember-lo),var(--ember-hi))}
.ad-art svg{width:34px;height:34px;fill:var(--on-ember)}
.ad-body h3{font-size:19px;font-weight:800;margin-bottom:6px}
.ad-body p{font-size:13.5px;color:var(--dim);line-height:1.5}


/* ---------- badge picker ---------- */
.badges{display:grid;grid-template-columns:repeat(4,1fr);gap:8px}
.badges button{
  background:var(--panel);border:1.5px solid var(--line2);border-radius:12px;
  padding:11px 4px;color:var(--dim);font:inherit;font-size:11.5px;font-weight:600;
  display:flex;flex-direction:column;align-items:center;gap:6px;cursor:pointer;
}
.badges button i{width:20px;height:20px;border-radius:50%;display:block}
.badges button.on{color:var(--ink);border-color:var(--ember);background:rgba(255,106,26,.08)}

/* =====================================================================
   ORBIT — structure, not skin.
   The hero owns the screen: the post floats in weather, the headline sits
   under it, one pill starts the work. Controls do not exist until asked
   for. Beginning shrinks the hero to a header and lets the form scroll
   beneath it — the preview never leaves the screen and never moves again.
   ===================================================================== */

body{background:var(--bg)}
.app::before,.app::after{content:"";position:fixed;inset:0;pointer-events:none;z-index:0}
.app::before{background:radial-gradient(125% 78% at 50% 6%, var(--sky1) 0%, var(--sky2) 56%, var(--bg) 100%)}
.app::after{
  background:conic-gradient(from 0deg at 50% 38%, transparent 0deg,
    var(--halo-a) 62deg, transparent 132deg, var(--halo-b) 224deg, transparent 302deg);
  filter:blur(34px);opacity:.85;animation:orbit-sweep 26s linear infinite;will-change:transform;
}
@keyframes orbit-sweep{to{transform:rotate(360deg)}}
.screen::before{
  content:"";position:fixed;inset:0;pointer-events:none;z-index:1;opacity:.3;mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml;utf8,\
<svg xmlns='http://www.w3.org/2000/svg' width='120' height='120'>\
<filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/></filter>\
<rect width='120' height='120' filter='url(%23n)' opacity='0.5'/></svg>");
}
.screen{z-index:2}
.tabs{z-index:40}

/* --- the frame --- */
.brandline,.margin-note{
  position:fixed;z-index:4;pointer-events:none;font-family:var(--font-mono);
  font-size:8.5px;line-height:1.55;letter-spacing:1.9px;text-transform:uppercase;
  top:calc(var(--safe-t) + 20px);
}
.brandline{left:18px;color:var(--ink);font-weight:500}
.brandline span{color:var(--ember2)}
.margin-note{right:18px;color:var(--faint);text-align:right}
.brk{position:fixed;z-index:4;width:15px;height:42px;pointer-events:none;
  border:1px solid rgba(238,242,247,.24)}
.brk.tl{top:calc(var(--safe-t) + 62px);left:11px;border-right:0}
.brk.tr{top:calc(var(--safe-t) + 62px);right:11px;border-left:0}
.brk.bl{bottom:calc(var(--tabh) + var(--safe-b) + 18px);left:11px;border-right:0}
.brk.br{bottom:calc(var(--tabh) + var(--safe-b) + 18px);right:11px;border-left:0}

/* --- the hero --- */
.hero{
  position:relative;z-index:2;flex:1;min-height:0;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:18px;padding:76px 26px 22px;text-align:center;
  transition:flex-basis .5s cubic-bezier(.22,1,.36,1);
}
.hero .stage-card,.hero-empty{
  width:min(178px,44vw);aspect-ratio:9/16;border:0;border-radius:14px;margin:0;
  background:rgba(255,255,255,.045);overflow:hidden;flex:none;
  box-shadow:0 30px 70px -28px rgba(0,0,0,.95), 0 0 0 1px rgba(255,255,255,.07);
  animation:orbit-float 8s ease-in-out infinite;will-change:transform;
}
/* No backdrop-filter here: it survived the pass that took the other fourteen
   out, and it re-blurs the moving sky behind it every frame. */
.hero-empty{display:grid;place-items:center;border:1px dashed rgba(255,255,255,.2)}
/* An undrawn canvas is transparent, which would show as a hole in the card for
   the moment before the example is painted. Give it the card's own ground -
   in every mode. The card is grouped with the translucent panels elsewhere,
   but unlike them it is always filled by an opaque black card, so letting day
   mode paint it white just moved the flick: white box, then black card. */
.hero .stage-card{background:#000}
.hero-empty svg{width:30px;height:30px;fill:none;stroke:var(--ember2);stroke-width:1.6;
  stroke-linecap:round;stroke-linejoin:round}
.hero .stage-card canvas{width:100%;display:block}
@keyframes orbit-float{
  0%,100%{transform:translateY(0) rotate(-.4deg)}
  50%{transform:translateY(-8px) rotate(.35deg)}
}
.hero-say{display:flex;flex-direction:column;align-items:center;gap:13px;
  transition:opacity .32s ease}
.hero-h{font-family:var(--font-display);font-weight:200;font-size:29px;
  letter-spacing:-1.3px;line-height:1.08;color:var(--ink)}
.hero-h b{font-weight:600}
.hero-sub{font-family:var(--font-mono);font-size:9px;letter-spacing:2.4px;
  text-transform:uppercase;color:var(--dim)}
.pill{
  display:inline-flex;align-items:center;gap:10px;padding:14px 30px;border:0;
  border-radius:999px;background:var(--ink);color:var(--bg);cursor:pointer;
  font-family:var(--font-display);font-weight:600;font-size:15px;
  box-shadow:0 16px 38px -16px rgba(0,0,0,.9);
}
.pill::after{content:"→";font-weight:400;animation:orbit-nudge 2.8s ease-in-out infinite}
@keyframes orbit-nudge{0%,100%{transform:translateX(0)}50%{transform:translateX(4px)}}
.pill:active{transform:scale(.98)}

/* --- hero state: the controls do not exist --- */
#s-post[data-view="hero"] .body{display:none}
#s-post[data-view="hero"] .hero{flex:1}

/* --- work state: the hero becomes a header, the form scrolls under it --- */
#s-post[data-view="work"] .hero{
  flex:none;flex-direction:row;gap:14px;justify-content:flex-start;
  padding:70px 20px 12px;text-align:left;
}
#s-post[data-view="work"] .hero .stage-card,
#s-post[data-view="work"] .hero-empty{width:74px;animation:none}
#s-post[data-view="work"] .hero-say{display:none}
#s-post[data-view="work"] .hero::after{
  content:"Your post";font-family:var(--font-mono);font-size:9px;letter-spacing:2.2px;
  text-transform:uppercase;color:var(--faint);align-self:center;
}
#s-post[data-view="work"] .body{padding-top:4px}

/* --- surfaces are glass over the sky --- */
.picker,.seg,input[type=text],textarea,.badges button{
  background-color:rgba(255,255,255,.045);
  backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);
}
.picker{border:1px dashed rgba(255,255,255,.2);border-radius:16px}
.picker.has{border-style:solid;border-color:var(--ember)}
.seg{border:1px solid rgba(255,255,255,.12);border-radius:14px}
.seg button.on{background:rgba(255,255,255,.1);box-shadow:inset 0 0 0 1px var(--ember)}
input[type=text],textarea{border:1px solid rgba(255,255,255,.13);border-radius:13px}
.badges button{border:1px solid rgba(255,255,255,.12)}
.badges button.on{border-color:var(--ember);background:rgba(255,255,255,.09)}
.row{border-bottom:1px solid rgba(255,255,255,.08)}
.tabs{background:var(--tabbg);backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);
  border-top:1px solid rgba(255,255,255,.08)}
.lab{font-size:9.5px;letter-spacing:2.1px;color:var(--faint);font-weight:500}
.hl,.hdr h1{font-family:var(--font-display);font-weight:200;letter-spacing:-1.3px;font-size:30px}
.em{background:none;-webkit-background-clip:border-box;background-clip:border-box;color:var(--ember2)}
.bname{font-family:var(--font-display);font-weight:600}
.cta{
  border-radius:999px;background:var(--ink);color:var(--bg);
  font-family:var(--font-display);font-weight:600;font-size:15.5px;
  display:flex;align-items:center;justify-content:center;gap:11px;
  box-shadow:0 14px 34px -14px rgba(0,0,0,.9);
}
.cta::after{content:"→";font-weight:400}
.ghost{border-radius:999px;border-color:rgba(255,255,255,.16)}

@media (prefers-reduced-motion:reduce){
  .app::after,.hero .stage-card,.hero-empty,.pill::after{animation:none}
}

/* ---------------------------------------------------------------------
   DAY — the same weather at noon. A different sky, not a tint of night:
   pale and overcast, ink flipped, halos warmed, glass inverted from
   frosted-white to frosted-dark. Night is the default; auto follows the
   phone; choosing at all stays optional.
   --------------------------------------------------------------------- */
[data-mode="day"]{ --bg:#f1f5f9; --bg2:#e8eef5; --panel:#ffffff; --panel2:#f4f7fb; --line:#d5dee8; --line2:#bcc8d6; --ink:#0d1219; --dim:#4b5a6d; --faint:#6b7a8d; --tabbg:rgba(241,245,249,.9); --sky1:#dfeaf6; --sky2:#f3f6fa; --halo-a:rgba(80,150,230,.20); --halo-b:rgba(255,160,90,.16); }
[data-mode="day"][data-theme="violet"]{ --bg:#f1f5f9; --bg2:#e8eef5; --panel:#ffffff; --panel2:#f4f7fb; --line:#d5dee8; --line2:#bcc8d6; --ink:#0d1219; --dim:#4b5a6d; --faint:#6b7a8d; --tabbg:rgba(241,245,249,.9); --sky1:#e4dff5; --sky2:#f5f3fb; --halo-a:rgba(130,100,255,.20); --halo-b:rgba(255,140,210,.15); }
[data-mode="day"][data-theme="magenta"]{ --bg:#f1f5f9; --bg2:#e8eef5; --panel:#ffffff; --panel2:#f4f7fb; --line:#d5dee8; --line2:#bcc8d6; --ink:#0d1219; --dim:#4b5a6d; --faint:#6b7a8d; --tabbg:rgba(241,245,249,.9); --sky1:#f7e0e8; --sky2:#fdf4f7; --halo-a:rgba(255,90,150,.20); --halo-b:rgba(255,180,120,.15); }
[data-mode="day"][data-theme="cyan"]{ --bg:#f1f5f9; --bg2:#e8eef5; --panel:#ffffff; --panel2:#f4f7fb; --line:#d5dee8; --line2:#bcc8d6; --ink:#0d1219; --dim:#4b5a6d; --faint:#6b7a8d; --tabbg:rgba(241,245,249,.9); --sky1:#d8ecf6; --sky2:#f1f9fd; --halo-a:rgba(0,180,240,.20); --halo-b:rgba(90,230,200,.15); }
[data-mode="day"][data-theme="lime"]{ --bg:#f1f5f9; --bg2:#e8eef5; --panel:#ffffff; --panel2:#f4f7fb; --line:#d5dee8; --line2:#bcc8d6; --ink:#0d1219; --dim:#4b5a6d; --faint:#6b7a8d; --tabbg:rgba(241,245,249,.9); --sky1:#e4f0d4; --sky2:#f6faee; --halo-a:rgba(140,210,60,.20); --halo-b:rgba(240,220,110,.15); }
[data-mode="day"][data-theme="gold"]{ --bg:#f1f5f9; --bg2:#e8eef5; --panel:#ffffff; --panel2:#f4f7fb; --line:#d5dee8; --line2:#bcc8d6; --ink:#0d1219; --dim:#4b5a6d; --faint:#6b7a8d; --tabbg:rgba(241,245,249,.9); --sky1:#f7ecc9; --sky2:#fdf9ec; --halo-a:rgba(240,190,60,.22); --halo-b:rgba(255,150,80,.15); }
@media (prefers-color-scheme: light){
  [data-mode="auto"]{ --bg:#f1f5f9; --bg2:#e8eef5; --panel:#ffffff; --panel2:#f4f7fb; --line:#d5dee8; --line2:#bcc8d6; --ink:#0d1219; --dim:#4b5a6d; --faint:#6b7a8d; --tabbg:rgba(241,245,249,.9); --sky1:#dfeaf6; --sky2:#f3f6fa; --halo-a:rgba(80,150,230,.20); --halo-b:rgba(255,160,90,.16); }
  [data-mode="auto"][data-theme="violet"]{ --bg:#f1f5f9; --bg2:#e8eef5; --panel:#ffffff; --panel2:#f4f7fb; --line:#d5dee8; --line2:#bcc8d6; --ink:#0d1219; --dim:#4b5a6d; --faint:#6b7a8d; --tabbg:rgba(241,245,249,.9); --sky1:#e4dff5; --sky2:#f5f3fb; --halo-a:rgba(130,100,255,.20); --halo-b:rgba(255,140,210,.15); }
  [data-mode="auto"][data-theme="magenta"]{ --bg:#f1f5f9; --bg2:#e8eef5; --panel:#ffffff; --panel2:#f4f7fb; --line:#d5dee8; --line2:#bcc8d6; --ink:#0d1219; --dim:#4b5a6d; --faint:#6b7a8d; --tabbg:rgba(241,245,249,.9); --sky1:#f7e0e8; --sky2:#fdf4f7; --halo-a:rgba(255,90,150,.20); --halo-b:rgba(255,180,120,.15); }
  [data-mode="auto"][data-theme="cyan"]{ --bg:#f1f5f9; --bg2:#e8eef5; --panel:#ffffff; --panel2:#f4f7fb; --line:#d5dee8; --line2:#bcc8d6; --ink:#0d1219; --dim:#4b5a6d; --faint:#6b7a8d; --tabbg:rgba(241,245,249,.9); --sky1:#d8ecf6; --sky2:#f1f9fd; --halo-a:rgba(0,180,240,.20); --halo-b:rgba(90,230,200,.15); }
  [data-mode="auto"][data-theme="lime"]{ --bg:#f1f5f9; --bg2:#e8eef5; --panel:#ffffff; --panel2:#f4f7fb; --line:#d5dee8; --line2:#bcc8d6; --ink:#0d1219; --dim:#4b5a6d; --faint:#6b7a8d; --tabbg:rgba(241,245,249,.9); --sky1:#e4f0d4; --sky2:#f6faee; --halo-a:rgba(140,210,60,.20); --halo-b:rgba(240,220,110,.15); }
  [data-mode="auto"][data-theme="gold"]{ --bg:#f1f5f9; --bg2:#e8eef5; --panel:#ffffff; --panel2:#f4f7fb; --line:#d5dee8; --line2:#bcc8d6; --ink:#0d1219; --dim:#4b5a6d; --faint:#6b7a8d; --tabbg:rgba(241,245,249,.9); --sky1:#f7ecc9; --sky2:#fdf9ec; --halo-a:rgba(240,190,60,.22); --halo-b:rgba(255,150,80,.15); }
}
[data-mode="day"] .picker,[data-mode="day"] .seg,[data-mode="day"] input[type=text],[data-mode="day"] textarea,
[data-mode="day"] .badges button,[data-mode="day"] .hero-empty{background-color:rgba(255,255,255,.62)}
[data-mode="day"] .picker{border-color:rgba(13,18,25,.22)}
[data-mode="day"] .hero-empty{border-color:rgba(13,18,25,.22)}
[data-mode="day"] .seg,[data-mode="day"] input[type=text],[data-mode="day"] textarea,[data-mode="day"] .badges button{border-color:rgba(13,18,25,.14)}
[data-mode="day"] .seg button.on{background:rgba(255,255,255,.9)}
[data-mode="day"] .row{border-bottom-color:rgba(13,18,25,.1)}
[data-mode="day"] .tabs{border-top-color:rgba(13,18,25,.1)}
[data-mode="day"] .brk{border-color:rgba(13,18,25,.24)}
[data-mode="day"] .screen::before{opacity:.15}
[data-mode="day"] .hero .stage-card,[data-mode="day"] .hero-empty{
  box-shadow:0 30px 70px -30px rgba(13,18,25,.42), 0 0 0 1px rgba(13,18,25,.08)}
[data-mode="day"] .pill,[data-mode="day"] .cta{box-shadow:0 16px 38px -18px rgba(13,18,25,.55)}
@media (prefers-color-scheme: light){
  [data-mode="auto"] .picker,[data-mode="auto"] .seg,[data-mode="auto"] input[type=text],[data-mode="auto"] textarea,
  [data-mode="auto"] .badges button,[data-mode="auto"] .hero-empty{background-color:rgba(255,255,255,.62)}
  [data-mode="auto"] .picker{border-color:rgba(13,18,25,.22)}
  [data-mode="auto"] .hero-empty{border-color:rgba(13,18,25,.22)}
  [data-mode="auto"] .seg,[data-mode="auto"] input[type=text],[data-mode="auto"] textarea,[data-mode="auto"] .badges button{border-color:rgba(13,18,25,.14)}
  [data-mode="auto"] .seg button.on{background:rgba(255,255,255,.9)}
  [data-mode="auto"] .row{border-bottom-color:rgba(13,18,25,.1)}
  [data-mode="auto"] .tabs{border-top-color:rgba(13,18,25,.1)}
  [data-mode="auto"] .brk{border-color:rgba(13,18,25,.24)}
  [data-mode="auto"] .screen::before{opacity:.15}
  [data-mode="auto"] .hero .stage-card,[data-mode="auto"] .hero-empty{
    box-shadow:0 30px 70px -30px rgba(13,18,25,.42), 0 0 0 1px rgba(13,18,25,.08)}
  [data-mode="auto"] .pill,[data-mode="auto"] .cta{box-shadow:0 16px 38px -18px rgba(13,18,25,.55)}
}

/* The working header was a small thumb beside a large nothing. The preview
   earns more room, and the space next to it carries what you would otherwise
   scroll to check: the caption as it reads, and what you are about to export. */
.hero-meta{display:none}
#s-post[data-view="work"] .hero{gap:16px;align-items:stretch;padding:66px 20px 12px}
#s-post[data-view="work"] .hero .stage-card,
#s-post[data-view="work"] .hero-empty{width:112px}
#s-post[data-view="work"] .hero::after{content:none}
#s-post[data-view="work"] .hero-meta{
  display:flex;flex-direction:column;justify-content:center;gap:9px;
  flex:1;min-width:0;
}
.hero-cap{
  font-family:var(--font-display);font-weight:200;font-size:19px;line-height:1.2;
  letter-spacing:-.6px;color:var(--ink);
  display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;
}
.hero-cap.empty{color:var(--faint);font-weight:200}
.hero-spec{
  font-family:var(--font-mono);font-size:8.5px;letter-spacing:2px;text-transform:uppercase;
  color:var(--faint);
}

/* =====================================================================
   Bringing the build back in line with the mock.
   ===================================================================== */

/* 1 · The sky was too polite. The mock's atmosphere is stronger and moves
   on two axes: one sweep alone reads as a rotating smear, two at different
   speeds and directions read as weather. */
.app::after{
  opacity:1;filter:blur(30px);
  background:conic-gradient(from 0deg at 50% 40%, transparent 0deg,
    var(--halo-a) 58deg, transparent 128deg, var(--halo-b) 216deg, transparent 296deg);
  animation:orbit-sweep 22s linear infinite;
}
.app{position:relative}
.app > .sky2nd{
  content:"";position:fixed;inset:-15%;pointer-events:none;z-index:0;
  background:conic-gradient(from 180deg at 42% 62%, transparent 0deg,
    var(--halo-b) 80deg, transparent 165deg, var(--halo-a) 250deg, transparent 330deg);
  filter:blur(52px);opacity:.7;
  animation:orbit-sweep-b 34s linear infinite;will-change:transform;
}
@keyframes orbit-sweep-b{to{transform:rotate(-360deg)}}
.screen::before{opacity:.22}

/* 2 · The bar in the mock is not a tab bar. It is three words in the
   margin, weighted like the coordinates above them. */
.tabs{
  background:transparent;border-top:0;backdrop-filter:none;-webkit-backdrop-filter:none;
  height:calc(46px + var(--safe-b));padding:0 18px var(--safe-b);
  align-items:center;
}
.tabs button{
  flex:1;flex-direction:row;gap:6px;
  font-family:var(--font-mono);font-size:8.5px;letter-spacing:1.9px;text-transform:uppercase;
  color:var(--faint);font-weight:400;
}
.tabs button:first-child{justify-content:flex-start}
.tabs button:nth-child(2){justify-content:center}
.tabs button:last-child{justify-content:flex-end}
.tabs svg{display:none}
.tabs button.on{color:var(--ink);font-weight:500}
.tabs button.on::before{content:"◦";font-size:11px;line-height:1;color:var(--ember2)}

/* The sky-choice page sat at page black, so every tile read as a hole in it.
   Lift the ground it stands on, put real edges on the tiles, and let the
   chips carry their own light. */
.pick{background:var(--bg2)}
.pick::before{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:radial-gradient(120% 60% at 50% 0%, rgba(255,255,255,.07), transparent 70%);
}
.pick > *{position:relative}
.pick-tile{
  background:rgba(255,255,255,.05);
  border:1px solid rgba(255,255,255,.14);
  backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);
}
.pick-tile.on{
  border-color:var(--ember);
  background:rgba(255,255,255,.09);
  box-shadow:inset 0 0 0 1px var(--ember);
}
.pick-chip{
  border-radius:11px;
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.14), 0 8px 22px -12px rgba(0,0,0,.9);
}
.pick-name{color:var(--ink)}
.pick .psub{color:var(--dim)}

/* Day needs the opposite treatment: the tiles must sit *on* the page, not in it. */
[data-mode="day"] .pick-tile{background:rgba(255,255,255,.7);border-color:rgba(13,18,25,.14)}
[data-mode="day"] .pick-tile.on{background:#fff}
[data-mode="day"] .pick::before{background:radial-gradient(120% 60% at 50% 0%, rgba(13,18,25,.05), transparent 70%)}
@media (prefers-color-scheme: light){
  [data-mode="auto"] .pick-tile{background:rgba(255,255,255,.7);border-color:rgba(13,18,25,.14)}
  [data-mode="auto"] .pick-tile.on{background:#fff}
  [data-mode="auto"] .pick::before{background:radial-gradient(120% 60% at 50% 0%, rgba(13,18,25,.05), transparent 70%)}
}

/* =====================================================================
   The seam.
   In the working view the header is fixed and the form scrolls, but they
   shared an edge with nothing on it — no way to know the boundary was
   there, or that anything lay past it. Three parts: a rule that marks the
   edge, a shadow that only appears once something has gone under it, and
   a cue that names what is below and retires the moment you scroll.
   ===================================================================== */
.scroll-cue{display:none}
#s-post[data-view="work"] .scroll-cue{
  display:flex;align-items:center;justify-content:center;gap:6px;
  position:relative;z-index:3;margin:0;padding:9px 0 11px;
  font-family:var(--font-mono);font-size:8.5px;letter-spacing:2px;
  text-transform:uppercase;color:var(--faint);pointer-events:none;
  transition:opacity .3s ease;
}
.scroll-cue svg{
  width:12px;height:12px;fill:none;stroke:currentColor;stroke-width:2;
  stroke-linecap:round;stroke-linejoin:round;
  animation:cue-drift 2.4s ease-in-out infinite;
}
@keyframes cue-drift{0%,100%{transform:translateY(-1px)}50%{transform:translateY(2px)}}
#s-post.scrolled .scroll-cue{opacity:0}

#s-post[data-view="work"] .hero{
  border-bottom:1px solid rgba(255,255,255,.11);
  transition:box-shadow .22s ease, border-color .22s ease;
}
/* the shadow is evidence, not decoration: it exists only while something
   is actually passing beneath the header */
#s-post[data-view="work"].scrolled .hero{
  border-bottom-color:rgba(255,255,255,.18);
  box-shadow:0 14px 26px -20px rgba(0,0,0,1);
}

[data-mode="day"] #s-post[data-view="work"] .hero{border-bottom-color:rgba(13,18,25,.12)}
[data-mode="day"] #s-post[data-view="work"].scrolled .hero{
  border-bottom-color:rgba(13,18,25,.2);
  box-shadow:0 14px 26px -20px rgba(13,18,25,.5);
}
@media (prefers-color-scheme: light){
  [data-mode="auto"] #s-post[data-view="work"] .hero{border-bottom-color:rgba(13,18,25,.12)}
  [data-mode="auto"] #s-post[data-view="work"].scrolled .hero{
    border-bottom-color:rgba(13,18,25,.2);
    box-shadow:0 14px 26px -20px rgba(13,18,25,.5);
  }
}

/* =====================================================================
   POWER
   Measured in the working view: 14 visible surfaces carrying
   backdrop-filter over 0.65 of a screen, sitting on top of two
   full-viewport blurred layers rotating without end. Every frame the
   compositor was re-reading and re-blurring each of those 14 backdrops
   because the thing behind them had moved. That is the whole battery
   story, and it buys almost nothing: over a sky this soft, a translucent
   fill is indistinguishable from a blurred one.
   ===================================================================== */
.picker,.seg,input[type=text],textarea,.badges button,
.hero-empty,.tabs,.pick-tile{
  backdrop-filter:none;-webkit-backdrop-filter:none;
}
/* slightly more present, since there is no blur separating them now */
.picker,.seg,input[type=text],textarea,.badges button,.hero-empty{
  background-color:rgba(255,255,255,.07);
}
.seg button.on{background:rgba(255,255,255,.13)}
.pick-tile{background:rgba(255,255,255,.07)}
.tabs{background:var(--tabbg)}

[data-mode="day"] .picker,[data-mode="day"] .seg,[data-mode="day"] input[type=text],
[data-mode="day"] textarea,[data-mode="day"] .badges button,
[data-mode="day"] .hero-empty,[data-mode="day"] .pick-tile{background-color:rgba(255,255,255,.78)}
@media (prefers-color-scheme: light){
  [data-mode="auto"] .picker,[data-mode="auto"] .seg,[data-mode="auto"] input[type=text],
  [data-mode="auto"] textarea,[data-mode="auto"] .badges button,
  [data-mode="auto"] .hero-empty,[data-mode="auto"] .pick-tile{background-color:rgba(255,255,255,.78)}
}

/* The oversized layer was 488x1056 CSS px — 976x2112 device pixels at DPR 2 —
   blurred at 52px and spun forever. Smaller, softer, and it stops when the
   controls are covering it anyway. */
.app > .sky2nd{inset:-8%;filter:blur(40px);opacity:.6}
.app::after{filter:blur(26px)}
#s-post[data-view="work"] ~ * .sky2nd,
body.calm .sky2nd{animation-play-state:paused}
body.calm .app::after{animation-duration:44s}

/* =====================================================================
   1 · THE FLICKER
   In night the halos read as atmosphere. In day they sit on a near-white
   ground, where the same alphas become moving colour blotches — the eye
   reads that as flicker, not weather. Day gets its own, much quieter
   values and a slower turn.
   ===================================================================== */
[data-mode="day"]{ --halo-a:rgba(80,150,230,.09); --halo-b:rgba(255,160,90,.07); }
[data-mode="day"][data-theme="violet"]{ --halo-a:rgba(130,100,255,.09); --halo-b:rgba(255,140,210,.07) }
[data-mode="day"][data-theme="magenta"]{ --halo-a:rgba(255,90,150,.09); --halo-b:rgba(255,180,120,.07) }
[data-mode="day"][data-theme="cyan"]{ --halo-a:rgba(0,180,240,.09); --halo-b:rgba(90,230,200,.07) }
[data-mode="day"][data-theme="lime"]{ --halo-a:rgba(140,210,60,.09); --halo-b:rgba(240,220,110,.07) }
[data-mode="day"][data-theme="gold"]{ --halo-a:rgba(240,190,60,.10); --halo-b:rgba(255,150,80,.07) }
[data-mode="day"] .app::after{animation-duration:40s;opacity:.7}
[data-mode="day"] .sky2nd{opacity:.35;animation-duration:56s}
@media (prefers-color-scheme: light){
  [data-mode="auto"]{ --halo-a:rgba(80,150,230,.09); --halo-b:rgba(255,160,90,.07) }
  [data-mode="auto"] .app::after{animation-duration:40s;opacity:.7}
  [data-mode="auto"] .sky2nd{opacity:.35;animation-duration:56s}
}

/* =====================================================================
   2 · THE WAITING SCREEN
   It was a hardcoded warm-black at 90% with a blur on top, so over a pale
   sky it turned to murk and the text sat on it at --faint. This is the
   screen people stare at for minutes on a slow phone; it should be the
   best-looking thing in the app, not the worst.
   ===================================================================== */
.busy{
  background:var(--bg);
  backdrop-filter:none;-webkit-backdrop-filter:none;   /* murk, and a blur per frame */
  place-items:center;
}
.busy::before{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:radial-gradient(120% 70% at 50% 0%, var(--sky1), var(--bg) 62%);
  opacity:.9;
}
.busy-in{position:relative;max-width:320px;padding:0 28px}

.busy-in p#busy-msg{
  font-family:var(--font-display);font-weight:200;font-size:26px;
  letter-spacing:-1px;line-height:1.1;color:var(--ink);margin-bottom:9px;
}
.busy-in .note#busy-sub{
  font-family:var(--font-mono);font-size:10px;letter-spacing:1.8px;
  text-transform:uppercase;color:var(--dim);margin:0 0 26px;
}
.busy .ring{
  height:2px;border-radius:0;margin-bottom:30px;
  background:rgba(128,128,128,.28);
}
/* width animation relayouts every tick, and this runs during the heaviest
   work the app does. Scale a full-width bar instead. */
.busy .ring i{
  width:100%;transform:scaleX(0);transform-origin:left;
  transition:transform .18s linear;
  background:linear-gradient(90deg,var(--ember),var(--ember-hi));
}
.busy #busy-cancel{
  margin-top:0;color:var(--dim);border-color:rgba(128,128,128,.3);
  font-family:var(--font-mono);font-size:11px;letter-spacing:1.6px;text-transform:uppercase;
}

/* The waiting screen covers the tab bar, so its bottom brackets should not
   reserve room for it — otherwise the frame sits 64px off the floor. */
.busy .brk.bl,.busy .brk.br{bottom:calc(var(--safe-b) + 22px)}
.busy .margin-note{color:var(--dim)}

/* A size warning is advice, not an error - the file still goes through. Ember
   rather than red, so it reads as "watch out" and not "you did it wrong". */
.note.warn{color:var(--ember2)}

/* The privacy link is required to be findable, not to be loud. */
.quiet-link{color:var(--dim);text-decoration:underline;text-underline-offset:3px}

/* Build stamp on the colour picker. Deliberately faint - it is a diagnostic,
   not decoration. Tells you at a glance whether a phone is running a cached
   older build, which is otherwise very hard to tell apart from a bug. */
.build-stamp{font-family:var(--font-mono);font-size:8.5px;letter-spacing:1.6px;
  text-transform:uppercase;color:var(--faint);opacity:.55;margin-top:14px}

/* =====================================================================
   NO CONNECTION
   Above everything, including the busy screen and the ad, because it is
   the one condition under which nothing else should be reachable.
   ===================================================================== */
.offline{
  position:fixed; inset:0; z-index:90; display:grid; place-items:center;
  background:var(--bg); padding:0 30px;
}
.offline::before{
  content:""; position:absolute; inset:0; pointer-events:none;
  background:radial-gradient(120% 70% at 50% 0%, var(--sky1), var(--bg) 62%);
  opacity:.9;
}
.offline-in{position:relative; text-align:center; max-width:330px}
.offline-art{
  width:64px; height:64px; margin:0 auto 22px; display:grid; place-items:center;
  border-radius:18px; background:rgba(128,128,128,.10);
}
.offline-art svg{
  width:30px; height:30px; fill:none; stroke:var(--ember2); stroke-width:1.7;
  stroke-linecap:round;
}
.offline h3{
  font-family:var(--font-display); font-weight:200; font-size:27px;
  letter-spacing:-1px; color:var(--ink); margin-bottom:10px;
}
.offline p{color:var(--dim); font-size:14.5px; line-height:1.5}
.offline .note{
  font-family:var(--mono); font-size:10px; letter-spacing:1.6px;
  text-transform:uppercase; color:var(--faint); margin:20px 0 22px;
}
.offline .cta{width:100%}

/* --- back out of the work view -------------------------------------------
   The hero is a full-screen preview; the work view is the form. Going in was
   possible and coming out was not, which on a phone with no hardware back is
   simply a dead end. Only shown where it means something. */
.backer{
  display:none; flex:none; align-self:center;
  width:34px; height:34px; padding:0; border-radius:50%;
  background:transparent; border:1px solid var(--line2);
  color:var(--ink); align-items:center; justify-content:center;
  -webkit-tap-highlight-color:transparent;
}
.backer svg{
  width:17px; height:17px; fill:none; stroke:currentColor;
  stroke-width:1.9; stroke-linecap:round; stroke-linejoin:round;
}
.backer:active{background:rgba(128,128,128,.14)}
#s-post[data-view="work"] .backer{display:flex}
