/* XPRTIX — interface styles.
   Tokens, type scale and components follow the brand book (v1.0, chapters
   7, 8, 9 and 11). Dark ground, grey surfaces stepping up from it, and Brick
   only where something leaves or happens: the shard, the primary button, the
   drop zone. Keep Brick under a tenth of any screen. */

:root{
  color-scheme:dark;
  /* Ground and surfaces: each step is about +6 in lightness */
  --bg:#151515; --card:#1B1B1B; --card-hi:#212121;
  --surface:#272727; --line:#2E2E2E; --line-hi:#3A3A3A;
  /* Text */
  --fg:#FFFFFF; --fg-2:#A1A1A1; --fg-3:#8A8A8A;
  /* Brand. Red text on dark is always --accent-text; --accent is for fills,
     the shard and large shapes only (3:1 on Graphite). */
  --accent:#A04747; --accent-hi:#B85252; --accent-text:#D07272;
  --shard:var(--accent);
  /* Status: functional only, never decoration. Brick never means "error". */
  --good:#7BC49A; --busy:#D6A85C; --bad:#FF6B6B;
  /* Shape */
  --r-sm:7px; --r-md:10px; --r-lg:14px; --cut:18px;
  --glow:0 6px 24px -6px var(--accent);

  --sans:"Geist",ui-sans-serif,-apple-system,"Segoe UI",Roboto,sans-serif;
  --mono:"Geist Mono",ui-monospace,SFMono-Regular,Menlo,monospace;

  --wrap:1120px;
  --gutter:clamp(16px,4vw,32px);
  --top-h:64px;
  --ease:cubic-bezier(.2,.8,.2,1);
}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-padding-top:calc(var(--top-h) + 16px)}
body{
  margin:0;min-height:100vh;position:relative;overflow-x:hidden;
  background:var(--bg);color:var(--fg);
  font:400 16px/26px var(--sans);
  -webkit-font-smoothing:antialiased;
}
/* display:flex and grid would otherwise beat the attribute everywhere. */
[hidden]{display:none !important}
h1,h2,h3,p{margin:0}
h1,h2,h3{text-wrap:balance}
a{color:inherit}
button{font:inherit;color:inherit}
strong{font-weight:600;color:var(--fg)}
code,.mono{font-family:var(--mono)}
code{
  font-size:.86em;padding:.08em .38em;border-radius:5px;
  background:#ffffff0a;border:1px solid #ffffff0f;color:var(--fg);
  -webkit-box-decoration-break:clone;box-decoration-break:clone;
}
::selection{background:var(--accent);color:#fff}
:focus-visible{outline:2px solid var(--accent-text);outline-offset:3px}

/* Brand icons: 24 px grid, 2 px stroke, square caps, mitred joins, outline
   only, coloured by the text they sit beside. */
.i{fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;flex-shrink:0}

.wrap{width:100%;max-width:calc(var(--wrap) + 2 * var(--gutter));margin-inline:auto;padding-inline:var(--gutter)}

/* Anything a machine would write, set small and uppercase. */
.label{
  font:400 11px/16px var(--mono);letter-spacing:.1em;text-transform:uppercase;
  color:var(--fg-3);
}

.skip{
  position:absolute;left:-999px;top:12px;z-index:100;
  padding:8px 12px;border-radius:var(--r-sm);
  background:var(--fg);color:var(--bg);font-weight:600;text-decoration:none;
}
.skip:focus{left:16px}

/* One view at a time, chosen by html[data-tool] - set by the server for the
   first paint and by router.js after that. */
html:not([data-tool="home"]) [data-view="home"],
html:not([data-tool="video"]) [data-view="video"],
html:not([data-tool="image"]) [data-view="image"]{display:none}

@keyframes rise{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
@keyframes spin{to{transform:rotate(360deg)}}
@keyframes pulse{50%{opacity:.45}}

/* ---- The glow ----
   A soft blob from white to Brick at 30%, behind a 200 px blur, for depth.
   Two elements: the wrapper is positioned by JS, the inner one runs the
   morph keyframes; sharing one would let the animation overwrite the inline
   transform every frame. It sits off to the right until the pointer moves,
   and the header and footer are opaque enough that it never reads as being
   behind the logo. */
#blob{
  position:fixed;top:0;left:0;z-index:-2;
  width:min(46vw,34rem);aspect-ratio:1;
  transform:translate(62vw,8vh);
  will-change:transform;pointer-events:none;
}
#blob i{
  display:block;width:100%;height:100%;
  background-image:linear-gradient(to right,#fff,var(--accent));
  opacity:.30;
  animation:blobMorph 5s infinite ease-in-out;
}
#blobBlur{
  position:fixed;inset:0;z-index:-1;
  backdrop-filter:blur(200px);-webkit-backdrop-filter:blur(200px);
  pointer-events:none;
}
@keyframes blobMorph{
  0%{border-radius:50% 50% 50% 50%/50% 50% 50% 50%;transform:rotate(0) scale(1.1)}
  25%{border-radius:60% 40% 70% 40%/60% 50% 60% 40%;transform:rotate(30deg) scale(1.2,1.4)}
  50%{border-radius:50% 60% 50% 70%/70% 60% 50% 50%;transform:rotate(180deg) scale(1.3,1)}
  75%{border-radius:40% 70% 60% 50%/50% 60% 40% 60%;transform:rotate(300deg) scale(1.1,1.3)}
  100%{border-radius:50% 50% 50% 50%/50% 50% 50% 50%;transform:rotate(360deg) scale(1.1)}
}

/* ---- Header ---- */
.top{
  position:sticky;top:0;z-index:20;height:var(--top-h);
  background:rgba(21,21,21,.88);
  backdrop-filter:blur(16px) saturate(140%);-webkit-backdrop-filter:blur(16px) saturate(140%);
  border-bottom:1px solid var(--line);
}
.top-in{height:100%;display:flex;align-items:center;justify-content:space-between;gap:16px}

/* Product lockup: the drawn logo, then the tool name in Geist Medium with
   its capitals at the logo's cap height and half a cap height between them.
   Both are SVGs on the same 108-unit box, so they share a baseline exactly.
   At 18 px tall the logo is 107 px wide, above the 96 px minimum. */
.lockup{display:flex;align-items:center;height:18px;color:var(--fg);text-decoration:none;flex-shrink:0}
.lockup svg{display:block;height:100%;width:auto;overflow:visible}
.lockup-logo{aspect-ratio:640/108}
.lockup-name{aspect-ratio:490/108}
.lockup-name text{fill:var(--fg-2);font:500 137px var(--sans);letter-spacing:-4px}
html[data-tool="home"] .lockup-name{display:none}

/* Tools: a segmented control, one link per tool. */
.toolnav{
  display:flex;gap:4px;padding:3px;
  background:var(--bg);border:1px solid var(--line);border-radius:var(--r-md);
}
.toolnav a{
  display:inline-flex;align-items:center;gap:8px;height:32px;padding:0 12px;
  border-radius:var(--r-sm);
  font:500 13px/1 var(--sans);color:var(--fg-2);text-decoration:none;
  transition:background .2s,color .2s;
}
.toolnav a:hover{color:var(--fg);background:#ffffff08}
.toolnav a[aria-current="page"]{
  background:var(--surface);color:var(--fg);font-weight:600;
  box-shadow:inset 0 0 0 1px #ffffff0a;
}
.toolnav a:focus-visible{outline-offset:1px}

/* How many files a tool is holding. Amber while any of them is working. */
.count{
  display:inline-grid;place-items:center;min-width:18px;height:18px;padding:0 5px;
  border-radius:999px;background:#ffffff14;color:var(--fg);
  font:500 11px/1 var(--mono);
}
.count.busy{background:rgba(214,168,92,.16);color:var(--busy)}

@media (max-width:560px){
  .lockup .lockup-name{display:none}
  .toolnav a{padding:0 10px}
}

/* ---- Type ---- */
.display{font:800 clamp(44px,7.4vw,72px)/1 var(--sans);letter-spacing:-.04em}
h1{font:800 clamp(34px,5vw,48px)/1.05 var(--sans);letter-spacing:-.035em}
h1:focus{outline:none}
h2{font:700 clamp(24px,3.2vw,30px)/1.15 var(--sans);letter-spacing:-.02em}
h3{font:600 18px/26px var(--sans);letter-spacing:-.01em}
.lede{font-size:17px;line-height:28px;color:var(--fg-2);max-width:34rem}

/* ---- Hero ---- */
.hero{
  display:grid;grid-template-columns:minmax(0,1.05fr) minmax(0,1fr);
  gap:clamp(32px,6vw,72px);align-items:center;
  padding-block:clamp(48px,9vh,96px) clamp(32px,5vh,56px);
}
.hero-copy{display:grid;gap:20px;justify-items:start;align-content:center}
.hero-copy .label{color:var(--accent-text)}
@media (max-width:880px){
  .hero{grid-template-columns:1fr}
}

/* What a tool changes, as the change itself. Squared, so they never read as
   a status pill. */
.specs{display:flex;flex-wrap:wrap;gap:6px}
.specs > span{
  font:500 12px/1 var(--mono);color:var(--fg-2);white-space:nowrap;
  padding:7px 9px;border-radius:var(--r-sm);
  background:#ffffff05;border:1px solid var(--line);
}

/* ---- Drop zone ----
   The one cut corner per view. The cut is the logo's own geometry: at a
   scale where the cut is 100 units, the shard sits exactly where the X's
   arm was cut free, 16 units away. The hairline border is the wrapper's
   ::before showing through its 1 px padding; the inner cut is 0.59 px shorter so
   the diagonal edge is exactly as thick as the straight ones. */
.dz-wrap{--cut:32px;position:relative;isolation:isolate;padding:1px}
.dz-wrap::before{
  content:"";position:absolute;inset:0;z-index:-1;
  background:var(--line-hi);
  clip-path:polygon(0 0,calc(100% - var(--cut)) 0,100% var(--cut),100% 100%,0 100%);
  transition:background .25s;
}
.dz{
  position:relative;
  display:grid;justify-items:center;align-content:center;gap:8px;
  min-height:320px;padding:40px 24px;text-align:center;cursor:pointer;
  /* The 4-unit module grid, as a faint dot field. */
  background:
    radial-gradient(circle at 1px 1px,#ffffff12 1px,transparent 1.5px) 0 0/16px 16px,
    var(--card);
  clip-path:polygon(0 0,calc(100% - var(--cut) + .59px) 0,100% calc(var(--cut) - .59px),100% 100%,0 100%);
  transition:background-color .25s;
}
.dz:focus-visible{outline:none}
.dz-wrap:hover::before{background:#4a4a4a}
.dz-wrap:has(.dz:focus-visible)::before{background:var(--accent-text)}
.dz-wrap.over::before{background:var(--accent)}
.dz-wrap.over .dz{
  background:
    radial-gradient(circle at 1px 1px,#ffffff18 1px,transparent 1.5px) 0 0/16px 16px,
    linear-gradient(rgba(160,71,71,.10),rgba(160,71,71,.10)),
    var(--card);
}

.dz-icon{
  display:grid;place-items:center;width:52px;height:52px;margin-bottom:8px;
  border-radius:var(--r-md);border:1px solid var(--line-hi);background:var(--bg);
  transition:transform .25s var(--ease),color .25s,border-color .25s;
}
.dz-wrap:hover .dz-icon{transform:translateY(-2px)}
.dz-wrap.over .dz-icon{transform:translateY(-6px);color:var(--accent-text);border-color:var(--accent)}
.dz-title{font:600 20px/28px var(--sans);letter-spacing:-.01em}
.dz-hint{font-size:14px;line-height:22px;color:var(--fg-2)}
.dz-formats{display:flex;flex-wrap:wrap;justify-content:center;gap:4px;margin-top:10px}
.dz-formats span{
  font:500 11px/1 var(--mono);letter-spacing:.04em;color:var(--fg-2);
  padding:5px 7px;border-radius:5px;background:#ffffff08;border:1px solid #ffffff0d;
}
.dz-limit{font:400 11px/16px var(--mono);letter-spacing:.1em;text-transform:uppercase;color:var(--fg-3);margin-top:4px}

/* The shard: 0.58 x 0.42 of the cut, the logo's shard polygon in its own box.
   It loosens on hover, pulls away while a file is held over the zone, and
   leaves on drop while a new one settles into place. */
.dz-shard{
  position:absolute;top:0;right:0;
  width:calc(var(--cut) * .58);height:calc(var(--cut) * .42);
  background:var(--shard);
  clip-path:polygon(44.83% 0,100% 0,27.59% 100%,0 61.9%);
  pointer-events:none;
  transition:transform .35s var(--ease);
}
.dz-wrap:hover .dz-shard{transform:translate(2px,-2px)}
.dz-wrap.over .dz-shard{transform:translate(7px,-7px)}
.dz-wrap.sent .dz-shard{animation:shardOut .9s var(--ease)}
@keyframes shardOut{
  0%{transform:translate(7px,-7px);opacity:1}
  40%{transform:translate(56px,-56px);opacity:0}
  41%{transform:translate(-4px,4px);opacity:0}
  100%{transform:none;opacity:1}
}

/* ---- Sections ---- */
.block{padding-top:clamp(64px,10vh,112px)}
.block-head{display:grid;gap:12px;max-width:44rem;margin-bottom:32px}
.block-head > p:not(.label){color:var(--fg-2)}

/* ---- Home: tools ---- */
.tools{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:16px}
.tool-card{
  display:flex;flex-direction:column;gap:16px;padding:24px;
  background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);
  color:var(--fg);text-decoration:none;
  transition:border-color .25s,background .25s;
}
.tool-card:hover{border-color:var(--line-hi);background:var(--card-hi)}
.tool-top{display:flex;align-items:center;gap:14px}
.tool-top .label{flex:1}
.tool-icon{
  display:grid;place-items:center;width:44px;height:44px;
  border-radius:var(--r-md);background:var(--surface);border:1px solid #ffffff0a;
}
/* The export arrow: the brand's action icon, always up and to the right. */
.go{color:var(--fg-3);transition:transform .25s var(--ease),color .25s}
.tool-card:hover .go{transform:translate(3px,-3px);color:var(--accent-text)}
.tool-name{font:800 40px/1 var(--sans);letter-spacing:-.035em}
.tool-desc{color:var(--fg-2);max-width:30rem}
.tool-foot{
  display:flex;align-items:center;justify-content:space-between;gap:8px;
  margin-top:auto;padding-top:16px;border-top:1px solid var(--line);
}
@media (max-width:760px){.tools{grid-template-columns:1fr}}

/* ---- Home: how it works ---- */
.flow{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:16px}
.flow li{
  position:relative;display:flex;flex-direction:column;gap:10px;padding:24px;
  background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);
}
.flow li > p{color:var(--fg-2);font-size:15px;line-height:24px}
/* A step reads into the next one, left to right like the logo. */
.flow li:not(:last-child)::after{
  content:"";position:absolute;z-index:1;top:50%;right:-13px;
  width:10px;height:10px;margin-top:-5px;
  border-top:2px solid var(--line-hi);border-right:2px solid var(--line-hi);
  transform:rotate(45deg);
}
.readout{
  display:grid;gap:2px;margin-top:auto;padding:12px 14px;
  border-radius:var(--r-md);background:var(--bg);border:1px solid var(--line);
  font:400 13px/20px var(--mono);
}
.readout .dim{color:var(--fg-3)}
.readout .good{color:var(--good)}
.readout .bad{color:var(--bad)}
@media (max-width:880px){
  .flow{grid-template-columns:1fr}
  .flow li:not(:last-child)::after{top:auto;bottom:-13px;right:50%;margin:0 -5px 0 0;transform:rotate(135deg)}
}

/* ---- Home: principles ---- */
.principles{
  list-style:none;margin:0;padding:0;
  display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:1px;
  background:var(--line);border:1px solid var(--line);border-radius:var(--r-lg);overflow:hidden;
}
.principles li{display:flex;flex-direction:column;gap:8px;padding:24px;background:var(--bg)}
.principles .label{color:var(--accent-text)}
.principles p{font-size:14px;line-height:22px;color:var(--fg-2)}
@media (max-width:880px){.principles{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:520px){.principles{grid-template-columns:1fr}}

/* ---- Status pills: mono, pill-shaped, tinted at 8% ---- */
.pill,.badge{
  display:inline-flex;align-items:center;gap:6px;flex-shrink:0;white-space:nowrap;
  font:500 12px/16px var(--mono);padding:4px 9px;border-radius:999px;border:1px solid;
}
.pill .i{width:13px;height:13px}
.good:is(.pill,.badge){color:var(--good);border-color:rgba(123,196,154,.35);background:rgba(123,196,154,.08)}
.busy:is(.pill,.badge){color:var(--busy);border-color:rgba(214,168,92,.35);background:rgba(214,168,92,.08)}
.bad:is(.pill,.badge){color:var(--bad);border-color:rgba(255,107,107,.35);background:rgba(255,107,107,.08)}
/* Waiting for the user rather than for the tool: neutral, not amber. */
.badge.idle{color:var(--fg-2);border-color:var(--line-hi);background:#ffffff08}

/* Working: a square turning on its corner, the logo's only other angle. */
.spin{
  width:8px;height:8px;border:1.5px solid currentColor;
  animation:spin 1.4s linear infinite;
}

/* ---- Buttons ----
   One primary per view: Brick, and the only thing that carries the glow.
   Radius 10, height 40. */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
  height:40px;padding:0 16px;border-radius:var(--r-md);
  font:600 14px/1 var(--sans);color:var(--fg);text-decoration:none;white-space:nowrap;
  background:none;border:1px solid transparent;cursor:pointer;
  transition:background .2s,border-color .2s,color .2s,box-shadow .2s,transform .1s;
}
.btn:active{transform:translateY(1px)}
.btn.sm{height:34px;padding:0 12px;font-size:13px}
.btn.primary{background:var(--accent);box-shadow:var(--glow)}
.btn.primary:hover{background:var(--accent-hi)}
.btn.secondary{background:var(--card-hi);border-color:var(--line)}
.btn.secondary:hover{background:var(--surface);border-color:var(--line-hi)}
.btn.ghost{color:var(--fg-2)}
.btn.ghost:hover{color:var(--fg);background:#ffffff0a}
.btn:disabled{opacity:.4;cursor:default;box-shadow:none;transform:none}
.btn.working{cursor:progress}
/* Saving is an export: the arrow takes the brand's text red, except on a
   Brick button, where it stays white like the label. */
.btn.save .i{color:var(--accent-text)}
.btn.save.primary .i{color:currentColor}
/* Already saved: quieter, but still fully clickable. */
.btn.save.again{color:var(--fg-2)}
.btn.save.again .i{color:var(--good)}

.icon-btn{
  display:inline-grid;place-items:center;flex-shrink:0;width:32px;height:32px;padding:0;
  border:0;border-radius:var(--r-sm);background:none;color:var(--fg-3);cursor:pointer;
  transition:background .2s,color .2s;
}
.icon-btn:hover{color:var(--fg);background:#ffffff0d}
.icon-btn:focus-visible{outline-offset:1px}

/* ---- Workspace ---- */
.work{display:grid;gap:12px}
.work-split{grid-template-columns:340px minmax(0,1fr);align-items:start;gap:24px}
.work-main{display:grid;gap:12px;min-width:0}
@media (max-width:880px){.work-split{grid-template-columns:1fr}}

.toolbar{
  display:flex;align-items:center;flex-wrap:wrap;gap:6px;
  padding:8px 8px 8px 16px;
  background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);
  animation:rise .3s both;
}
.count-text{flex:1;min-width:12rem;font:400 13px/20px var(--mono);color:var(--fg-2)}

.results{display:grid;gap:10px}

.empty{
  padding:32px 20px;text-align:center;font-size:14px;line-height:22px;color:var(--fg-3);
  border:1px dashed var(--line-hi);border-radius:var(--r-lg);
}
.results.has-items ~ .empty{display:none}

/* ---- File cards ---- */
.card{
  position:relative;display:grid;gap:12px;padding:14px;
  background:var(--card-hi);border:1px solid var(--line);border-radius:var(--r-lg);
  /* Only on first insert - see .is-new. Re-running an entry animation on
     every state change made cards blink out and fade back in. */
  transition:opacity .25s,border-color .3s,background .3s,transform .25s;
}
.card.is-new{animation:rise .35s var(--ease) both}
.card[data-tone="good"]{border-color:rgba(123,196,154,.22)}
.card[data-tone="bad"]{border-color:rgba(255,107,107,.26)}
/* Saved cards recede so outstanding work reads first. */
.card.is-saved{background:var(--card)}
.card.is-saved:not(:hover) .card-main{opacity:.7}
/* Leaving the list: shrink away rather than vanish. */
.card.is-going{opacity:0;transform:translateY(-4px) scale(.985);pointer-events:none}

.card-main{display:flex;align-items:center;gap:12px;min-width:0;transition:opacity .25s}

/* The file's extension stands in for a thumbnail a video cannot cheaply
   give. Neutral: the badge carries the state. */
.card-tile,.card-thumb{
  position:relative;display:grid;place-items:center;flex-shrink:0;overflow:hidden;
  width:44px;height:44px;border-radius:var(--r-md);
  background:var(--bg);border:1px solid var(--line);color:var(--fg-3);
}
.card-tile{font:500 11px/1 var(--mono);letter-spacing:.04em;color:var(--fg-2)}
.card-thumb{width:52px;height:52px}
.card-thumb img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}

.card-text{flex:1;min-width:0;display:grid;gap:2px}
.card-name{font:500 14px/20px var(--mono);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* Size and time: separated by a dot drawn in CSS, so copying the text keeps
   the space between them. */
.card-meta{display:flex;flex-wrap:wrap;gap:0 8px;font:400 12px/18px var(--mono);color:var(--fg-3)}
.card-meta > * + *::before{content:"\00b7";margin-right:8px}
.card-x:hover{color:var(--bad);background:rgba(255,107,107,.1)}

/* A final outcome, said in words: a tinted block with the status icon, a
   title and the reason. Status colours report a result; they never decorate. */
.verdict{
  display:flex;align-items:flex-start;gap:12px;padding:12px 14px;
  border:1px solid;border-radius:var(--r-md);
}
.verdict[data-tone="good"]{background:rgba(123,196,154,.07);border-color:rgba(123,196,154,.24)}
.verdict[data-tone="bad"]{background:rgba(255,107,107,.06);border-color:rgba(255,107,107,.26)}
.verdict-icon{
  display:grid;place-items:center;flex-shrink:0;width:32px;height:32px;border-radius:var(--r-sm);
}
.verdict[data-tone="good"] .verdict-icon{color:var(--good);background:rgba(123,196,154,.14)}
.verdict[data-tone="bad"] .verdict-icon{color:var(--bad);background:rgba(255,107,107,.12)}
.verdict-text{display:grid;gap:2px;min-width:0;padding-top:5px}
.verdict-title{font-size:15px;line-height:22px;font-weight:600}
.verdict-why{font-size:14px;line-height:22px;color:var(--fg-2)}
.verdict-why:empty{display:none}

/* Each fix: the change itself, then why it mattered, in two columns that
   line up from row to row. */
.card-fixes{
  list-style:none;margin:0;padding:0;
  display:grid;grid-template-columns:max-content minmax(0,1fr);
  background:var(--card);border:1px solid var(--line);border-radius:var(--r-md);
}
.card-fixes li{
  grid-column:1 / -1;display:grid;grid-template-columns:subgrid;align-items:center;
  column-gap:14px;row-gap:6px;padding:10px 12px;
}
.card-fixes li + li{border-top:1px solid var(--line)}
.card-fixes .pill{justify-self:start}
.card-fixes .why{font-size:14px;line-height:20px;color:var(--fg-2)}

/* The finished-file row from the brand book: what happened on the left,
   what to do next on the right, so an action never sits alone on a line. */
.card-foot{
  display:flex;align-items:center;flex-wrap:wrap;gap:10px 16px;
  padding-top:12px;border-top:1px solid var(--line);
}
.card-foot:not(:has(.card-note:not(:empty),.card-out:not(:empty),.card-actions > :not([hidden]))){display:none}
.card-foot > p{flex:1 1 16rem;min-width:0}

.card-note{display:flex;align-items:center;gap:8px;font-size:13px;line-height:20px;color:var(--fg-2)}
.card-note .i{flex-shrink:0;color:var(--fg-3)}
.card-note:empty{display:none}
/* An image's note sits above the footer, on its own line. */
.card > .card-note{font-size:14px;line-height:22px}
.card[data-tone="bad"] > .card-note{color:var(--fg)}

/* The output line: planned settings before, size comparison after. */
.card-out{display:flex;flex-wrap:wrap;align-items:center;gap:6px 10px;font:400 12px/18px var(--mono);color:var(--fg-2)}
.card-out:empty{display:none}
.card-out > span + span:not(.chip)::before{content:"\00b7";margin-right:10px;color:var(--fg-3)}
.card-out .cmp{font-weight:500}
.card-out .cmp b{font-weight:500;margin-left:4px}
.card-out .cmp.shrank{color:var(--good)}
.card-out .cmp.grew{color:var(--busy)}
.card-out .chip{padding:2px 7px;border-radius:5px;background:#ffffff0a;border:1px solid #ffffff10;color:var(--fg-2)}

.bar{height:3px;border-radius:2px;background:var(--surface);overflow:hidden}
.bar i{display:block;height:100%;border-radius:2px;background:var(--busy);transition:width .5s ease;animation:pulse 1.6s ease-in-out infinite}
/* A real percentage does not need the pulse - the movement is the feedback. */
.bar.is-known i{animation:none}

.card-actions{display:flex;flex-wrap:wrap;gap:8px;margin-left:auto}
.card-actions:not(:has(> :not([hidden]))){display:none}
/* Every card's Save is Brick, so the glow stays with the view's one primary. */
.card .btn.primary{box-shadow:none}

/* The export moment: up to three shards leave the card's top-right corner,
   shrinking and fading, the way the logo's shard leaves the X. */
.shards{position:absolute;top:0;right:0;width:0;height:0;pointer-events:none}
.shards i{
  position:absolute;right:-4px;top:-10px;
  width:calc(20px - var(--i) * 5px);aspect-ratio:58/42;
  opacity:calc(1 - var(--i) * .3);color:var(--shard);
}
.shards svg{
  display:block;width:100%;height:100%;fill:currentColor;
  animation:shardFly .95s var(--ease) both;animation-delay:calc(var(--i) * 80ms);
}
@keyframes shardFly{
  0%{transform:translate(-10px,10px);opacity:0}
  25%{opacity:1}
  100%{transform:translate(28px,-28px);opacity:0}
}

/* ---- Files that were not added ---- */
.skipped{
  display:flex;align-items:flex-start;gap:12px;
  padding:14px 10px 14px 16px;
  background:rgba(214,168,92,.06);border:1px solid rgba(214,168,92,.3);border-radius:var(--r-lg);
  animation:rise .3s both;
}
.hero-drop .skipped{margin-top:12px}
.skipped-icon{color:var(--busy);padding-top:2px;display:flex}
.skipped-text{flex:1;min-width:0;display:grid;gap:4px}
.skipped-title{font-size:14px;line-height:22px;font-weight:600}
.skipped-added{font-weight:400;color:var(--good)}
.skipped-why{font-size:14px;line-height:22px;color:var(--fg-2)}
.skipped-list{list-style:none;margin:4px 0 0;padding:0;font:400 12px/18px var(--mono);color:var(--fg-3)}
.skipped-list li{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.skipped-act{justify-self:start;margin-top:8px}
.skipped-act .i{color:var(--accent-text)}

/* ---- Image output settings ---- */
.panel{
  display:grid;gap:22px;padding:20px;
  background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);
}
.settings{position:sticky;top:calc(var(--top-h) + 16px)}
@media (max-width:880px){.settings{position:static}}

/* The title, and the whole setting in one mono line under it. */
.panel-head{display:grid;gap:2px;padding-bottom:16px;margin-bottom:-6px;border-bottom:1px solid var(--line)}
.panel-title{font-size:16px;line-height:24px;font-weight:600;letter-spacing:-.01em}
.panel-sum{font:400 12px/18px var(--mono);color:var(--fg-2)}

.opt{display:grid;gap:10px;min-width:0;margin:0;padding:0;border:0}
.opt-label{
  display:flex;justify-content:space-between;align-items:center;gap:8px;width:100%;
  padding:0;font-size:13px;line-height:20px;font-weight:500;
}
.opt-label output{
  padding:1px 7px;border-radius:5px;background:var(--bg);border:1px solid var(--line);
  font:500 12px/18px var(--mono);color:var(--fg);
}

/* Format: a tile per format the browser can write, each saying what it is
   for. The chosen one takes Brick and the shard in its corner. */
.fmt-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px}
.fmt{position:relative;display:block}
.fmt input{position:absolute;inset:0;margin:0;opacity:0;cursor:pointer}
.fmt > span{
  position:relative;display:grid;align-content:start;gap:2px;height:100%;padding:9px 11px 10px;
  background:var(--bg);border:1px solid var(--line);border-radius:var(--r-md);
  transition:background .2s,border-color .2s;
}
.fmt b{font:500 13px/18px var(--mono);color:var(--fg-2);transition:color .2s}
.fmt small{font-size:12px;line-height:16px;color:var(--fg-3)}
.fmt:hover > span{border-color:var(--line-hi);background:#ffffff05}
.fmt:hover b{color:var(--fg)}
.fmt input:checked + span{background:rgba(160,71,71,.1);border-color:var(--accent)}
.fmt input:checked + span b{color:var(--fg)}
.fmt input:checked + span::after{
  content:"";position:absolute;top:7px;right:7px;width:12px;aspect-ratio:58/42;
  background:var(--shard);clip-path:polygon(44.83% 0,100% 0,27.59% 100%,0 61.9%);
}
.fmt input:focus-visible + span{outline:2px solid var(--accent-text);outline-offset:2px}

.opt-note{
  margin-top:-10px;padding-left:10px;border-left:2px solid var(--busy);
  font-size:13px;line-height:20px;color:var(--fg-2);
}
.opt-note:empty{display:none}

/* Quick sizes under the scale slider. */
.presets{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:4px}
.presets button{
  height:28px;padding:0;border:1px solid var(--line);border-radius:var(--r-sm);
  background:var(--bg);font:500 12px/1 var(--mono);color:var(--fg-2);cursor:pointer;
  transition:background .2s,border-color .2s,color .2s;
}
.presets button:hover{color:var(--fg);border-color:var(--line-hi)}
.presets button[aria-pressed="true"]{background:var(--surface);border-color:var(--line-hi);color:var(--fg)}

/* What each end of a slider means. */
.range-ends{
  display:flex;justify-content:space-between;gap:8px;margin-top:-6px;
  font:400 11px/16px var(--mono);color:var(--fg-3);
}

.opt-hint{
  display:flex;align-items:flex-start;gap:10px;padding:12px;
  background:#ffffff05;border:1px solid var(--line);border-radius:var(--r-md);
  font-size:13px;line-height:20px;color:var(--fg-3);
}
.opt-hint .i{flex-shrink:0;margin-top:2px;color:var(--fg-2)}
.opt-hint strong{font-weight:500;color:var(--fg-2)}

/* Sliders. The filled part of the track is --p, set from JS: no browser
   draws one that can be styled the same way everywhere. */
input[type=range]{
  -webkit-appearance:none;appearance:none;
  width:100%;height:20px;margin:0;background:transparent;cursor:pointer;
  --p:50%;
}
input[type=range]::-webkit-slider-runnable-track{
  height:4px;border-radius:2px;
  background:linear-gradient(to right,var(--accent) var(--p),var(--surface) var(--p));
}
input[type=range]::-moz-range-track{height:4px;border-radius:2px;background:var(--surface)}
input[type=range]::-moz-range-progress{height:4px;border-radius:2px;background:var(--accent)}
input[type=range]::-webkit-slider-thumb{
  -webkit-appearance:none;width:16px;height:16px;margin-top:-6px;border:0;border-radius:50%;
  background:var(--fg);box-shadow:0 0 0 4px rgba(160,71,71,.28);transition:box-shadow .2s;
}
input[type=range]::-moz-range-thumb{
  width:16px;height:16px;border:0;border-radius:50%;
  background:var(--fg);box-shadow:0 0 0 4px rgba(160,71,71,.28);
}
input[type=range]:focus-visible{outline:none}
input[type=range]:focus-visible::-webkit-slider-thumb{box-shadow:0 0 0 4px var(--accent-text)}
input[type=range]:focus-visible::-moz-range-thumb{box-shadow:0 0 0 4px var(--accent-text)}

/* ---- Crawlable content ---- */
.reasons{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:16px}
.reason{
  display:flex;flex-direction:column;align-items:flex-start;gap:10px;padding:24px;
  background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);
}
.reason-num{font:500 12px/16px var(--mono);letter-spacing:.1em;color:var(--accent-text)}
.reason p{font-size:15px;line-height:24px;color:var(--fg-2)}
.reason .pill{margin-top:auto}
@media (max-width:760px){.reasons{grid-template-columns:1fr}}

/* What leaves the device, said as a ledger: three columns, no hedging. */
.ledger{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:16px}
.ledger-col{
  display:grid;gap:14px;align-content:start;padding:24px;
  background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);
}
.ledger-k{
  display:flex;align-items:center;gap:10px;
  font:500 12px/16px var(--mono);letter-spacing:.1em;text-transform:uppercase;color:var(--fg);
}
.ledger-k::before{content:"";width:8px;height:8px;border-radius:2px;background:var(--fg-3)}
.ledger-col.good .ledger-k::before{background:var(--good)}
.ledger-col.busy .ledger-k::before{background:var(--busy)}
.ledger ul{list-style:none;margin:0;padding:0;display:grid;gap:10px}
.ledger li{position:relative;padding-left:16px;font-size:14px;line-height:22px;color:var(--fg-2)}
.ledger li::before{content:"";position:absolute;left:0;top:11px;width:7px;height:1px;background:var(--fg-3)}
@media (max-width:880px){.ledger{grid-template-columns:1fr}}

/* FAQ accordion.
   The answer is always in the DOM - crawlers read it whether open or not.
   Animating grid-template-rows gives a real open/close transition, which
   height:auto cannot do. faq.js keeps one open at a time. */
.faq details{border-top:1px solid var(--line);max-width:52rem}
.faq details:last-of-type{border-bottom:1px solid var(--line)}
.faq summary{
  display:flex;align-items:center;gap:16px;padding:18px 4px;cursor:pointer;list-style:none;
  font:500 16px/24px var(--sans);
  /* Double-clicking a question should not select its text. */
  -webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;
  transition:color .2s;
}
.faq summary::-webkit-details-marker{display:none}
.faq summary:hover{color:var(--fg-2)}
.faq summary:focus-visible{outline-offset:-2px;border-radius:var(--r-sm)}
/* A plus that turns into a cross: the logo's 45 degrees. */
.faq summary::after{
  content:"";flex-shrink:0;margin-left:auto;width:12px;height:12px;
  background:
    linear-gradient(currentColor,currentColor) center/12px 2px no-repeat,
    linear-gradient(currentColor,currentColor) center/2px 12px no-repeat;
  color:var(--fg-3);
  transition:transform .3s var(--ease),color .2s;
}
.faq details.is-open summary::after{transform:rotate(45deg);color:var(--accent-text)}
.faq .answer{display:grid;grid-template-rows:0fr;transition:grid-template-rows .3s var(--ease)}
.faq .answer > div{overflow:hidden}
.faq .answer p{
  padding:0 40px 20px 4px;max-width:44rem;
  font-size:15px;line-height:24px;color:var(--fg-2);
  -webkit-user-select:text;user-select:text;
}

/* ---- Footer ----
   Solid ground: the glow never sits behind the logo. */
.foot{margin-top:clamp(80px,12vh,136px);background:var(--bg);border-top:1px solid var(--line)}
.foot-in{display:grid;grid-template-columns:1.4fr 1fr 1.4fr;gap:32px;padding-block:48px 40px}
.foot-logo{display:inline-block;width:128px;color:var(--fg)}
.foot-logo svg{display:block;width:100%;height:auto}
.foot-tag{margin-top:16px;color:var(--fg-2)}
/* The maker's credit: Geist Regular at caption size, under the logo. */
.credit{margin-top:2px;font-size:13px;line-height:20px;color:var(--fg-3)}
.credit a{color:var(--fg-2);text-decoration:none;border-bottom:1px solid var(--line-hi);transition:color .2s,border-color .2s}
.credit a:hover{color:var(--fg);border-color:var(--fg-3)}
.foot-col{display:grid;gap:8px;align-content:start;font-size:14px;line-height:22px;color:var(--fg-2)}
.foot-col .label{margin-bottom:4px}
.foot-col a{width:max-content;color:var(--fg-2);text-decoration:none;transition:color .2s}
.foot-col a:hover{color:var(--fg)}
.foot-col .mono{font-size:13px;color:var(--fg)}
.foot-base{
  display:flex;justify-content:space-between;flex-wrap:wrap;gap:8px;
  padding-block:20px 32px;
  /* A rule the width of the content, not of the gutters around it. */
  background:linear-gradient(var(--line),var(--line)) var(--gutter) 0/calc(100% - 2 * var(--gutter)) 1px no-repeat;
  font-size:13px;line-height:20px;color:var(--fg-3);
}
.foot-base .mono{font-size:12px}
@media (max-width:760px){.foot-in{grid-template-columns:1fr}}

/* ---- Toast ---- */
.toast{
  position:fixed;left:50%;bottom:24px;z-index:50;
  display:flex;align-items:center;gap:16px;width:max-content;max-width:calc(100vw - 32px);
  padding:10px 12px 10px 16px;
  background:var(--surface);border:1px solid var(--line-hi);border-radius:var(--r-lg);
  box-shadow:0 16px 40px -12px #000;
  font-size:14px;line-height:22px;
  transform:translateX(-50%);animation:toastIn .3s var(--ease) both;
  transition:opacity .3s,transform .3s;
}
.toast.out{opacity:0;transform:translate(-50%,8px)}
.toast a{display:inline-flex;align-items:center;gap:6px;flex-shrink:0;color:var(--accent-text);font-weight:600;text-decoration:none}
.toast a:hover{color:var(--fg)}
@keyframes toastIn{from{opacity:0;transform:translate(-50%,12px)}}

/* ---- Image editor ---- */
html:has(dialog.editor[open]){overflow:hidden}
.editor{
  width:min(46rem,calc(100vw - 2rem));max-height:calc(100dvh - 2rem);
  padding:0;overflow:auto;
  background:var(--card);color:var(--fg);
  border:1px solid var(--line-hi);border-radius:var(--r-lg);
  box-shadow:0 30px 80px -20px #000;
}
.editor::backdrop{background:rgba(0,0,0,.72);backdrop-filter:blur(4px)}
.ed-head{display:flex;align-items:center;gap:12px;padding:16px 18px 12px}
.ed-titles{flex:1;min-width:0;display:grid;gap:2px}
.ed-name{font:500 15px/22px var(--mono);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* The stage clips the crop box's dimming shadow; its padding leaves room for
   handles sitting on the image's edge. */
.ed-stage{
  display:grid;place-items:center;overflow:hidden;
  margin:0 18px;padding:14px;
  background:
    radial-gradient(circle at 1px 1px,#ffffff0d 1px,transparent 1.5px) 0 0/16px 16px,
    #0f0f0f;
  border-radius:var(--r-md);
}
.ed-frame{position:relative;line-height:0;cursor:crosshair;touch-action:none;-webkit-user-select:none;user-select:none}
/* Sized by fitPreview() in cropper.js. */
.ed-frame canvas{display:block}
.ed-crop{position:absolute;cursor:move;outline:1.5px solid #fff;box-shadow:0 0 0 100vmax rgba(0,0,0,.65)}
.ed-crop:focus-visible{outline:2px solid var(--accent-text);outline-offset:0}
/* Thirds, the usual composition guide. */
.ed-crop::before{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:
    linear-gradient(90deg,transparent calc(100%/3 - .5px),#ffffff40 0 calc(100%/3 + .5px),transparent 0 calc(200%/3 - .5px),#ffffff40 0 calc(200%/3 + .5px),transparent 0),
    linear-gradient(180deg,transparent calc(100%/3 - .5px),#ffffff40 0 calc(100%/3 + .5px),transparent 0 calc(200%/3 - .5px),#ffffff40 0 calc(200%/3 + .5px),transparent 0);
}
/* Square handles: the grid has no round corners. */
.ed-h{position:absolute;width:12px;height:12px;background:#fff;box-shadow:0 0 0 1px rgba(0,0,0,.4)}
/* A larger invisible target than the visible handle, for fingers. */
.ed-h::after{content:"";position:absolute;inset:-10px}
.ed-h[data-h="nw"]{left:-6px;top:-6px;cursor:nwse-resize}
.ed-h[data-h="ne"]{right:-6px;top:-6px;cursor:nesw-resize}
.ed-h[data-h="se"]{right:-6px;bottom:-6px;cursor:nwse-resize}
.ed-h[data-h="sw"]{left:-6px;bottom:-6px;cursor:nesw-resize}
.ed-h[data-h="n"],.ed-h[data-h="s"]{left:50%;width:24px;height:6px;margin-left:-12px;cursor:ns-resize}
.ed-h[data-h="n"]{top:-3px}
.ed-h[data-h="s"]{bottom:-3px}
.ed-h[data-h="e"],.ed-h[data-h="w"]{top:50%;width:6px;height:24px;margin-top:-12px;cursor:ew-resize}
.ed-h[data-h="e"]{right:-3px}
.ed-h[data-h="w"]{left:-3px}

.ed-tools{display:flex;flex-wrap:wrap;justify-content:space-between;gap:8px;padding:14px 18px 0}
.ed-seg{display:flex;flex-wrap:wrap;gap:3px;padding:3px;background:var(--bg);border:1px solid var(--line);border-radius:var(--r-md)}
.ed-seg button{
  display:grid;place-items:center;min-width:34px;height:30px;padding:0 9px;
  background:none;border:0;border-radius:var(--r-sm);
  color:var(--fg-2);cursor:pointer;font:500 12px/1 var(--mono);
  transition:background .2s,color .2s;
}
.ed-seg button:hover{color:var(--fg);background:#ffffff08}
.ed-seg button[aria-pressed="true"]{background:var(--surface);color:var(--fg);box-shadow:inset 0 0 0 1px #ffffff12}
.ed-seg button:focus-visible{outline-offset:1px}

.ed-fields{display:grid;grid-template-columns:repeat(4,1fr);gap:8px;padding:14px 18px 0}
.ed-fields label{display:grid;gap:4px;min-width:0}
.ed-fields span{font:400 11px/16px var(--mono);letter-spacing:.1em;text-transform:uppercase;color:var(--fg-3)}
.ed-fields input{
  width:100%;min-width:0;height:36px;padding:0 10px;
  background:var(--bg);color:var(--fg);border:1px solid var(--line);border-radius:var(--r-sm);
  font:400 13px/1 var(--mono);
}
.ed-fields input:hover{border-color:var(--line-hi)}
.ed-fields input:focus-visible{outline-offset:1px}

.ed-scale{display:flex;align-items:center;gap:12px;padding:16px 18px 0;font-size:13px}
.ed-scale label{font-weight:500}
.ed-scale input[type=range]{flex:1;width:auto}
.ed-scale-val{min-width:6.5rem;font:400 12px/20px var(--mono);color:var(--fg-2)}
.ed-link{
  padding:0;background:none;border:0;cursor:pointer;
  color:var(--accent-text);font:600 13px/20px var(--sans);
}
.ed-link:hover{color:var(--fg)}

.ed-foot{display:flex;align-items:center;gap:8px;margin-top:18px;padding:14px 18px 16px;border-top:1px solid var(--line)}
.ed-out{flex:1;display:flex;align-items:baseline;gap:8px;font:400 13px/20px var(--mono);color:var(--fg-2)}
.ed-out strong{font-weight:500}

/* ---- Small screens ---- */
@media (max-width:520px){
  .dz{min-height:240px;padding:32px 16px}
  .card{padding:12px}
  /* The badge moves under the name, so the name and its details keep the
     full width rather than wrapping around a pill. */
  .card-main{
    display:grid;grid-template-columns:auto minmax(0,1fr) auto;
    align-items:start;gap:6px 12px;
  }
  .card-tile,.card-thumb{grid-row:1 / 3}
  .card-text{grid-column:2}
  .card-main .badge{grid-column:2;grid-row:2;justify-self:start}
  .card-x{grid-column:3;grid-row:1}
  /* When it was added matters least, and is what made the details wrap. */
  .card-meta time{display:none}
  .card-actions{flex:1 1 100%}
  .card-actions .btn{flex:1}
  .card-fixes{grid-template-columns:minmax(0,1fr)}
  .verdict{padding:12px}
  .count-text{flex-basis:100%;margin-bottom:2px}
  .toolbar{padding:10px}
  .toolbar .btn{flex:1}
  .ed-fields{grid-template-columns:repeat(2,1fr)}
  .ed-foot{flex-wrap:wrap}
  .ed-out{flex-basis:100%;margin-bottom:4px}
  .ed-scale{flex-wrap:wrap}
  .ed-scale input[type=range]{flex-basis:100%;order:3}
}

::-webkit-scrollbar{width:8px}
::-webkit-scrollbar-track{background:var(--bg)}
::-webkit-scrollbar-thumb{background:var(--surface);border-radius:4px}
::-webkit-scrollbar-thumb:hover{background:var(--line-hi)}

@media (prefers-reduced-motion:reduce){
  #blob i{animation:none;opacity:.22}
  .card.is-new,.toolbar,.skipped,.toast{animation:none}
  .spin{animation:none;opacity:.6}
  .dz-wrap.sent .dz-shard{animation:none}
  .faq .answer,.faq summary::after{transition:none}
}

/* "Keep original" leads the formats and takes the full width. */
.fmt:has(input[value="keep"]){grid-column:1 / -1}
