/* ============================================================
   Convertburda — shared design tokens & components
   All colors live here as CSS variables (rule 2). No hex outside :root.
   ============================================================ */
:root {
  --bg: #eef1f5;
  --paper: #ffffff;
  /* header matches the logo's own background so the JPG blends in seamlessly */
  --header-bg: rgba(255, 255, 255, .92);
  --ink: #111820;
  --muted: #5b6673;
  --line: #dbe1e9;
  --accent: #d98a1f;
  --accent-ink: #5a3808;
  --accent2: #2f7dd9;
  --accent2-ink: #123a63;
  --accent3: #1f9e7c;
  --accent3-ink: #0f5c46;
  --grid-line: #e3e8ef;
  --ad-bg: #eff3f8;
  --ad-line: #c9d3df;
  --ok: #2f7d4f;
  --danger: #a3341f;
  --shadow-sm: rgba(17, 24, 32, .05);
  --shadow-lg: rgba(17, 24, 32, .28);
  /* the logo is a white-background JPG; it keeps its own white badge in dark mode */
  --logo-bg: #ffffff;
  --radius: 10px;
  --mono: ui-monospace, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
  --ui: system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

/* Dark theme (Fikret's light/dark toggle, 2026-07-10) — same accents, inverted surfaces */
:root[data-theme="dark"] {
  --bg: #10141a;
  --paper: #1a212b;
  --header-bg: rgba(21, 27, 35, .92);
  --ink: #e7ecf3;
  --muted: #9aa6b5;
  --line: #2d3745;
  --accent: #e39b33;
  --accent-ink: #f0c896;
  --accent2: #4f97e8;
  --accent2-ink: #a8cdf5;
  --accent3: #4dcda8;
  --accent3-ink: #a8f0da;
  --grid-line: #202834;
  --ad-bg: #171d26;
  --ad-line: #313d4c;
  --ok: #58b183;
  --danger: #e06a52;
  --shadow-sm: rgba(0, 0, 0, .25);
  --shadow-lg: rgba(0, 0, 0, .55);
}

* { box-sizing: border-box; }
html, body { margin: 0; }
body {
  font-family: var(--ui);
  color: var(--ink);
  background:
    radial-gradient(1100px 520px at 15% -10%, color-mix(in srgb, var(--accent) 10%, transparent), transparent),
    radial-gradient(900px 460px at 100% 0%, color-mix(in srgb, var(--accent2) 8%, transparent), transparent),
    var(--bg);
  background-attachment: fixed;
  position: relative;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}
/* grid overlay removed (Fikret 2026-07-10): clean color wash only */
a { color: var(--accent-ink); }
@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}

/* ---- header ---- */
header {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--header-bg);
  backdrop-filter: blur(6px);
  border-bottom: 1px solid var(--line);
}
header::before {
  content: "";
  display: block;
  height: 3px;
  background: linear-gradient(90deg, var(--accent), var(--accent2));
}
.bar { max-width: 1180px; margin: 0 auto; display: flex; align-items: center; gap: 18px; padding: 12px 18px; }
.logo { font-weight: 800; letter-spacing: -.02em; font-size: 19px; display: flex; align-items: center; gap: 9px; text-decoration: none; color: var(--ink); }
.logo img { height: 54px; width: auto; display: block; }
.logo .mark { width: 22px; height: 22px; border: 2px solid var(--ink); border-radius: 5px; position: relative; flex: none; }
.logo .mark::after { content: ""; position: absolute; inset: 4px 4px auto auto; width: 6px; height: 6px; background: var(--accent); border-radius: 1px; }
.spacer { flex: 1; }
.ghost { background: none; border: 1px solid var(--line); color: var(--ink); padding: 8px 13px; border-radius: 8px; font: inherit; font-size: 14px; cursor: pointer; text-decoration: none; display: inline-block; }
.ghost:hover { border-color: var(--muted); }
.ghost.active { border-color: var(--accent2); color: var(--accent2-ink); background: color-mix(in srgb, var(--accent2) 12%, transparent); }
.pro { border-color: var(--accent); color: var(--accent-ink); }
.pro-short { display: none; }

/* Phone/tablet header (2026-07-13 — Fikret's iPhone screenshot: the Pro button fell
   off the right edge). His chosen fix: shrink the ribbon logo ~45% on small screens
   and tighten the spacing; additionally the Pro button shows just "Pro" and the
   account button drops its text — both then match the header's existing icon-box
   pattern (flag/view/theme), with title/aria-label keeping them accessible. */
@media (max-width: 840px) {
  .bar { gap: 8px; padding: 10px 10px; }
  .logo img { height: 30px; }
  .bar .ghost { padding: 7px 9px; font-size: 13px; }
  .account-label, .pro-full { display: none; }
  .pro-short { display: inline; }
}
button:focus-visible, a:focus-visible, label:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ---- layout (rule 1: fixed-ratio, never deforms on resize) ----
   Simplified 2026-07-20: the ad no longer lives inside .wrap as a grid column —
   it's ONE sticky slot (see .ad-rail below) positioned against the viewport, set
   once by _Layout.cshtml for every page. .wrap just centers its own content, same
   as it would if ads didn't exist at all. */
.wrap { max-width: 1180px; margin: 0 auto; padding: 22px 18px 60px; }
main { min-width: 0; }

/* ---- the one ad slot (Fikret 2026-07-20: "1 sticky one rechtsboven vertikaal") ----
   Softened box while AdSense approval is pending (a loud dashed box reads as
   unfinished, not ad-supported) — once real units go live, <ins class="adsbygoogle">
   replaces this box and this styling stops applying. Positioned with a viewport
   calc rather than a grid column: sits just right of .wrap's centered content
   (max-width 1180px), further out on a studio page (.wide, max-width 1400px).
   Sticky, so it stays in view while the page scrolls, per Fikret's own pasted
   ad-strategy source. Hidden below ~1400/1620px — tablets, most laptops and every
   phone never see it, matching Fikret's "don't let the widening show on small
   screens" goal; AdSense Auto Ads (Anchor/Vignette, dashboard-configured, not
   here) is the intended mobile monetization layer instead. */
.ad-rail {
  position: fixed; top: 90px; width: 160px;
  left: calc((100vw + 1180px) / 2 + 20px);
}
.ad-rail.wide { left: calc((100vw + 1400px) / 2 + 20px); }
@media (max-width: 1400px) { .ad-rail:not(.wide) { display: none; } }
@media (max-width: 1620px) { .ad-rail.wide { display: none; } }
.ad {
  background: var(--ad-bg); border: 1px solid color-mix(in srgb, var(--ad-line) 55%, transparent); border-radius: 8px;
  color: color-mix(in srgb, var(--muted) 40%, var(--ad-bg)); font-size: 10px; letter-spacing: .08em; text-transform: uppercase;
  display: flex; align-items: center; justify-content: center; text-align: center;
  min-height: 600px;
  /* hard boundary (Fikret 2026-07-17): whatever creative Google eventually loads,
     it can never spill over neighbouring tiles/text — the slot clips, full stop */
  overflow: hidden;
}
/* same guarantee once a real AdSense unit replaces the placeholder: the <ins> can
   never grow wider than its slot, and anything oversized inside it is clipped */
ins.adsbygoogle { display: block; max-width: 100%; overflow: hidden; }

/* ---- category page's full tool listing (2026-07-20, Fikret) ---- */
.tool-listing dt { margin-top: 16px; }
.tool-listing dt:first-child { margin-top: 0; }
.tool-listing dt a { font-weight: 700; font-size: 15px; color: var(--ink); text-decoration: none; }
.tool-listing dt a:hover { color: var(--accent-ink); text-decoration: underline; }
.tool-listing dd { margin: 2px 0 0; color: var(--muted); font-size: 13.5px; }

/* ---- preview watermark guard (2026-07-20, Fikret) ----
   A screen-recording/screenshot can't tell watermark pixels from "real" pixels — so this
   is a real, rendered DOM overlay, not something CSS could hide from a capture tool. The
   pattern (a tiled, rotated SVG background-image) is generated once in JS per container;
   see window.cbPreviewGuard in site.js. pointer-events:none keeps it from ever blocking
   the download button or video controls underneath. */
.preview-guard { position: absolute; inset: 0; pointer-events: none; z-index: 5; background-repeat: repeat; }
/* the little "?" that explains the preview marking (2026-07-21) — sits above the guard,
   clickable, discreet; only added for viewers who actually see the marking (site.js). */
.preview-guard-help {
  position: absolute; top: 6px; left: 6px; z-index: 6;
  width: 22px; height: 22px; padding: 0; border: 0; border-radius: 50%;
  font: 700 13px/22px Arial, sans-serif; text-align: center; cursor: pointer;
  background: rgba(0,0,0,.45); color: #fff; opacity: .6; transition: opacity .15s;
}
.preview-guard-help:hover, .preview-guard-help:focus-visible { opacity: 1; }

/* ---- tool / content card (homogeneous container, rule 3) ---- */
.tool {
  position: relative;
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius); padding: 24px 22px 22px;
  box-shadow: 0 1px 2px var(--shadow-sm), 0 14px 38px -18px var(--shadow-lg);
  overflow: hidden;
}
.tool::before {
  content: "";
  position: absolute; top: 0; left: 0; right: 0; height: 3px;
  background: linear-gradient(90deg, var(--accent), var(--accent2));
}
.eyebrow {
  font-family: var(--mono); font-size: 12px; color: var(--accent-ink); letter-spacing: .04em;
  display: inline-flex; align-items: center; gap: 7px;
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  padding: 3px 10px; border-radius: 999px;
}
h1 { font-size: 26px; line-height: 1.15; letter-spacing: -.02em; margin: 6px 0 6px; }
.lede { color: var(--muted); margin: 0 0 18px; max-width: 60ch; }

.drop {
  border: 2px dashed var(--line); border-radius: 10px; padding: 30px 18px; text-align: center;
  background: color-mix(in srgb, var(--paper) 92%, var(--bg)); transition: border-color .15s, background .15s, box-shadow .15s; cursor: pointer;
  display: block;
}
.drop.drag { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, var(--paper)); }
/* action zones light up in the primary accent so the eye goes straight to them */
.drop:hover, .drop:focus-visible {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent);
}
.drop strong { display: block; font-size: 15px; }
.drop small { color: var(--muted); }
/* ---- compact source row (2026-07-18, Fikret's "1 foto to rule them all"):
   the big dashed box ate the top of every tool page. It becomes one modest
   button — and where a tool already has its own source buttons (microphone /
   add audio file) it disappears entirely, because those buttons load the file
   themselves. Dragging still works: the WHOLE tool card is the drop target
   (site.js), so the habit survives without costing any space. */
.drop.drop-compact {
  display: inline-flex; align-items: center; gap: 8px;
  border: 1px solid var(--line); border-style: solid; border-width: 1px;
  padding: 9px 16px; text-align: start; min-width: 230px; width: auto;
  background: color-mix(in srgb, var(--accent) 7%, var(--paper));
}
.drop.drop-compact::before { content: '📂'; font-size: 15px; line-height: 1; }
.drop.drop-compact strong { display: inline; font-size: 14px; font-weight: 600; }
.drop.drop-compact small { display: none; } /* the hint moves to the tooltip */
.drop.drop-hidden { display: none; }
/* the source buttons sit on one line, left-aligned, a touch roomier */
.src-row { margin: 12px 0; gap: 10px; }
.src-row .ghost, .src-row .cb-mic, .src-row .cb-mic-add { min-width: 190px; justify-content: center; padding: 9px 16px; }
/* the card itself lights up while a file is dragged over it */
.tool.drag-over { outline: 2px dashed var(--accent); outline-offset: 6px; }
input[type=file] { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }

.row { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; margin: 14px 0; }

/* ---------- editor workspace: canvas left, one properties panel right ----------
   (Fikret 2026-07-15) Stacking every control BELOW a 74vh canvas meant you could never
   see the photo and the slider you were dragging at the same time — by the time you
   scrolled to "Size", half the image was gone. So the controls move beside the canvas,
   the model every real editor uses (he works in Photopea). One panel, not two: one
   place to look, and the canvas keeps the full remaining width.
   Shared classes, not per-page CSS — Image transparency and Cut out shapes reuse these
   verbatim, so the three tools cannot drift apart. */
.editor { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 14px; align-items: start; }
.editor-canvas { min-width: 0; }
/* Deliberately NO max-height/overflow here: a scrollbar inside the panel hid "Flatten &
   download" below its own fold — re-creating, in miniature, the exact bug this layout
   exists to kill. The panel is simply as tall as its contents; if that runs a little past
   the canvas, that costs a few pixels of page, not a lost button. */
.editor-panel {
  display: flex; flex-direction: column; gap: 9px;
  padding: 12px; border: 1px solid var(--line); border-radius: 8px;
  background: color-mix(in srgb, var(--accent2) 3%, var(--paper));
}
/* one control per block: caption line on top, the control itself below it full width */
.pfield { display: flex; flex-direction: column; gap: 5px; }
.plabel { font-size: 13px; color: var(--muted); display: flex; align-items: center; gap: 6px; }
.pval { margin-inline-start: auto; font-family: var(--mono); font-size: 12px; color: var(--ink); }
.panel-sep { border: 0; border-top: 1px solid var(--line); margin: 3px 0; width: 100%; }
.editor-panel label.fld { width: 100%; gap: 6px; }
.editor-panel label.fld input[type=range] { flex: 1 1 auto; min-width: 0; }
/* image-transparency ships its own hold-to-repeat stepper wrapper — let it fill the column too */
.editor-panel .stepper { display: flex; width: 100%; }
.editor-panel .stepper input[type=range] { flex: 1 1 auto; min-width: 0; }
/* rows inside the panel are stacked, not spaced out like full-width page rows */
.editor-panel .row { margin: 0; gap: 6px; }
/* The shape library is the one genuinely long list here — 22 buttons across four groups
   would otherwise stretch the panel to double the canvas. It scrolls on its own so the
   picker stays browsable while Apply/Download below it stay put. This is a scrollable
   LIST, not a hidden action — the rule it must not break is that no button disappears. */
#csShapePanel { max-height: 300px; overflow-y: auto; padding-inline-end: 4px; }
.editor-panel select { width: 100%; }
.editor-panel .full { width: 100%; text-align: center; }
.editor-panel .help-btn { margin-inline-start: 0; flex: none; }
.editor-panel .hint-text { font-size: 12.5px; line-height: 1.45; }
/* the panel is only a panel while there is room beside the canvas; below that it becomes
   an ordinary stacked block again (phones were never going to get a side column) */
@media (max-width: 900px) {
  .editor { grid-template-columns: minmax(0, 1fr); }
}

/* Fixed-size viewport (Fikret 2026-07-12): the box never grows/shrinks with the zoom
   level — the canvas zooms INSIDE it, centered while it fits, scrollable once it doesn't. */
#tCanvasWrap { width: 100%; height: 74vh; overflow: auto; border-radius: 8px; border: 1px solid var(--line); background: var(--paper); display: flex; }
#tCanvasWrap canvas {
  display: block; flex: none; margin: auto;
  cursor:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='21' height='21' viewBox='0 0 21 21'%3E%3Cg stroke='white' stroke-width='3' stroke-linecap='square'%3E%3Cline x1='10.5' y1='1' x2='10.5' y2='8'/%3E%3Cline x1='10.5' y1='13' x2='10.5' y2='20'/%3E%3Cline x1='1' y1='10.5' x2='8' y2='10.5'/%3E%3Cline x1='13' y1='10.5' x2='20' y2='10.5'/%3E%3C/g%3E%3Cg stroke='black' stroke-width='1' stroke-linecap='square'%3E%3Cline x1='10.5' y1='1' x2='10.5' y2='8'/%3E%3Cline x1='10.5' y1='13' x2='10.5' y2='20'/%3E%3Cline x1='1' y1='10.5' x2='8' y2='10.5'/%3E%3Cline x1='13' y1='10.5' x2='20' y2='10.5'/%3E%3C/g%3E%3Ccircle cx='10.5' cy='10.5' r='1' fill='red'/%3E%3C/svg%3E")
    10 10, crosshair;
}
#tCanvasWrap canvas.panning { cursor: grabbing; }

/* Photo Studio (2026-07-19): same fixed zoom viewport as the transparency tool,
   plus a colour-swatch palette for the drawing panel. */
#psCanvasWrap { width: 100%; height: 74vh; overflow: auto; border-radius: 8px; border: 1px solid var(--line); background: var(--paper); display: flex; }
#psCanvasWrap canvas { display: block; flex: none; margin: auto; touch-action: none; }
.ps-swatches { display: flex; flex-wrap: wrap; gap: 5px; margin: 4px 0; }
.ps-swatch { width: 22px; height: 22px; border-radius: 5px; border: 1px solid var(--line); padding: 0; cursor: pointer; }
.ps-tools { display: flex; flex-wrap: wrap; gap: 6px; }
.ps-tools .ghost { padding: 5px 10px; }
/* imported-shape chips in the shape picker (cut-out & photo studio) */
.cs-lib-item { display: inline-flex; align-items: center; }
.cs-lib-item .cs-lib-del { padding: 2px 6px; font-size: 11px; margin-inline-start: -2px; opacity: .6; }
.cs-lib-item .cs-lib-del:hover { opacity: 1; }
.ps-ctx { position: fixed; z-index: 60; background: var(--paper); border: 1px solid var(--line); border-radius: 8px; box-shadow: 0 6px 14px var(--shadow-sm), 0 22px 50px -24px var(--shadow-lg); display: flex; flex-direction: column; padding: 4px; min-width: 130px; }
.ps-ctx button { text-align: start; background: none; border: 0; padding: 6px 12px; border-radius: 5px; cursor: pointer; color: inherit; font-size: 13px; }
.ps-ctx button:hover:not(:disabled) { background: var(--line); }
.ps-ctx button:disabled { opacity: .4; cursor: default; }

/* image-to-dxf threshold preview: same fixed-viewport zoom/pan pattern */
#vPreviewWrap { width: 100%; height: 70vh; overflow: auto; border-radius: 8px; border: 1px solid var(--line); background: var(--paper); display: flex; margin-top: 10px; }
#vPreviewWrap canvas { display: block; flex: none; margin: auto; }
#vPreviewWrap canvas.panning { cursor: grabbing; }

/* image-transparency: help popover */
.help-btn { width: 26px; height: 26px; padding: 0; margin-inline-start: 8px; border-radius: 50%; font-weight: 700; display: inline-flex; align-items: center; justify-content: center; vertical-align: middle; }
.help-panel { margin: 10px 0 0; padding: 14px 16px; border: 1px solid var(--line); border-radius: 8px; background: color-mix(in srgb, var(--accent2) 6%, var(--paper)); }
.help-panel ul { margin: 8px 0 0; padding-inline-start: 20px; }
.help-panel li { margin: 4px 0; font-size: 14px; color: var(--ink); }

/* image-transparency: slider stepper +/- */
.stepper { display: inline-flex; align-items: center; gap: 6px; }
.stepper-btn { width: 26px; height: 26px; padding: 0; display: inline-flex; align-items: center; justify-content: center; font-size: 16px; line-height: 1; user-select: none; }

/* image-transparency: right-click context menu */
.context-menu {
  position: fixed; z-index: 60; min-width: 190px; padding: 6px;
  background: var(--paper); border: 1px solid var(--line); border-radius: 10px;
  box-shadow: 0 1px 2px var(--shadow-sm), 0 14px 38px -14px var(--shadow-lg);
}
.context-menu button {
  display: block; width: 100%; text-align: start; background: none; border: none;
  padding: 8px 10px; border-radius: 6px; cursor: pointer; font: inherit; font-size: 14px; color: var(--ink);
}
.context-menu button:hover, .context-menu button:focus-visible { background: color-mix(in srgb, var(--accent2) 12%, transparent); }

.meta.warn { color: var(--accent-ink); }
.btn {
  background: linear-gradient(180deg, color-mix(in srgb, var(--accent) 100%, white 8%), var(--accent));
  color: #211404; border: none; padding: 10px 16px; border-radius: 8px; font: inherit; font-weight: 600;
  cursor: pointer; text-decoration: none; display: inline-block;
  box-shadow: 0 6px 14px -8px color-mix(in srgb, var(--accent) 70%, transparent);
  transition: transform .1s ease, box-shadow .1s ease, filter .1s ease;
}
.btn:hover { filter: brightness(1.04); transform: translateY(-1px); box-shadow: 0 8px 18px -8px color-mix(in srgb, var(--accent) 75%, transparent); }
.btn[disabled] { opacity: .45; cursor: not-allowed; transform: none; box-shadow: none; }
input[type=range] { font: inherit; }
/* Fikret 2026-07-15, standing rule: EVERY slider gets − / + steppers so a value can be
   nudged exactly instead of fought with by dragging (and it's far kinder on a phone).
   site.js injects them automatically around every <input type=range> — no per-page markup. */
.ghost.range-step {
  flex: none; padding: 0; width: 28px; min-width: 28px; height: 28px;
  font-size: 15px; font-weight: 700; line-height: 1; border-radius: 7px;
  display: inline-flex; align-items: center; justify-content: center;
}
/* Fikret's crypto-page input style promoted to the site-wide standard (2026-07-10):
   soft filled fields, rounded, with a colored focus glow */
select,
input[type=text],
input[type=number],
input[type=password],
textarea {
  appearance: none;
  -webkit-appearance: none;
  background: var(--bg); border: 1px solid transparent; border-radius: 10px;
  padding: 9px 13px; font: inherit; font-size: 15px; color: var(--ink); outline: none;
  transition: border-color .15s ease, background .15s ease, box-shadow .15s ease;
}
select:focus,
input[type=text]:focus,
input[type=number]:focus,
input[type=password]:focus {
  border-color: var(--accent2); background: var(--paper);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent2) 18%, transparent);
}
select {
  padding-right: 32px; cursor: pointer; font-weight: 500;
  /* arrow color = --muted; data-URIs can't read CSS variables, hence the literal */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%235b6673'%3E%3Cpath d='M7 10l5 5 5-5z'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 10px center; background-size: 20px;
}
textarea {
  font-family: var(--mono); font-size: 13px; width: 100%; min-height: 160px; resize: vertical;
}
/* the big text areas light up in the PRIMARY accent (Fikret's focus rule) */
textarea:focus {
  border-color: var(--accent); background: var(--paper);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent);
}
label.fld { font-size: 14px; color: var(--muted); display: flex; align-items: center; gap: 8px; }
.unit-tag { color: var(--muted); font-size: 13px; font-weight: 400; }

/* code viewer */
.code { border: 1px solid var(--line); border-radius: 8px; overflow: auto; max-height: 420px; background: #0e141b; }
.code table { border-collapse: collapse; width: 100%; font-family: var(--mono); font-size: 13px; }
.code td { padding: 1px 10px; white-space: pre; vertical-align: top; }
.code td.ln { color: #5a6b7d; text-align: right; user-select: none; background: #0b1016; position: sticky; left: 0; width: 1%; }
.code td.src { color: #d6e2ee; }
.tok-g { color: #7fd1ff; }
.tok-m { color: #ffb86b; }
.tok-axis { color: #a6e3a1; }
.tok-fs { color: #f2c56b; }
.tok-n { color: #6a7d8f; }
.tok-com { color: #6a7d8f; font-style: italic; }
.tok-num { color: #e6edf3; }

/* light data table (results, reference values) */
.table-wrap { overflow-x: auto; margin-top: 12px; }
.table { border-collapse: collapse; width: 100%; font-size: 14px; }
.table td { padding: 7px 10px; border-bottom: 1px solid var(--line); }
.table tr:first-child td { border-top: 1px solid var(--line); }
.table td:last-child { text-align: right; font-family: var(--mono); }

.meta { font-family: var(--mono); font-size: 12px; color: var(--muted); margin-top: 10px; }
.result-ok, .result-bad { border-radius: 8px; padding: 12px 14px; font-size: 14px; }
.result-ok { background: color-mix(in srgb, var(--ok) 12%, white); border: 1px solid var(--ok); color: var(--ok); }
.result-bad { background: color-mix(in srgb, var(--danger) 10%, white); border: 1px solid var(--danger); color: var(--danger); }
.preview { margin-top: 12px; border: 1px solid var(--line); border-radius: 8px; padding: 10px; background: #fbfcfe; text-align: center; }
.preview img { max-width: 100%; max-height: 320px; border-radius: 4px; }
/* checkerboard = the universal "this has transparency" indicator (Photoshop/GIMP convention) —
   without it, a transparent PNG previewed on this near-white box looks identical to an opaque
   white one, so a successful transparency removal looked like it had done nothing at all. */
.preview.checkerboard {
  background-color: var(--paper);
  background-image:
    linear-gradient(45deg, var(--line) 25%, transparent 25%),
    linear-gradient(-45deg, var(--line) 25%, transparent 25%),
    linear-gradient(45deg, transparent 75%, var(--line) 75%),
    linear-gradient(-45deg, transparent 75%, var(--line) 75%);
  background-size: 20px 20px;
  background-position: 0 0, 0 10px, 10px -10px, -10px 0;
}

/* explainer under the tool (SEO copy) — its own card, not transparent-on-grid */
.explain {
  margin-top: 22px; background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 20px 22px; box-shadow: 0 1px 2px var(--shadow-sm);
}
.explain h2 { font-size: 16px; margin: 0 0 8px; color: var(--ink); }
.explain h2:not(:first-child) { margin-top: 18px; }
.explain h3 { font-size: 14.5px; margin: 20px 0 6px; color: var(--ink); }
.explain p { color: var(--muted); margin: 0 0 14px; max-width: 70ch; }
details { border: 1px solid var(--line); border-radius: 8px; padding: 10px 14px; margin-bottom: 8px; background: color-mix(in srgb, var(--ad-bg) 60%, white); }
details:hover { border-color: var(--accent); }
summary { cursor: pointer; font-weight: 600; font-size: 14px; }
details p { margin: 8px 0 2px; }

/* ---- waveform editor (shared audio-tool component, 2026-07-16) ---- */
.wave-editor { margin-top: 12px; }
.wave-editor .we-canvas-wrap {
  position: relative; /* anchors the hold-down time readout (2026-07-17) */
  border: 1px solid var(--line); border-radius: 8px; overflow: hidden;
  background: color-mix(in srgb, var(--accent2) 4%, var(--paper));
}
/* exact time (m:ss.mmm) while the pointer is held on the band (Fikret's video) */
.we-timetip {
  position: absolute; top: 4px; pointer-events: none;
  background: color-mix(in srgb, var(--ink) 85%, transparent); color: var(--paper);
  font-family: var(--mono); font-size: 11px; padding: 2px 7px; border-radius: 6px;
}
.wave-editor .we-zoom { display: inline-flex; gap: 4px; margin-inline-start: auto; }
.wave-editor canvas { display: block; width: 100%; cursor: crosshair; touch-action: none; }
.wave-editor .we-top { align-items: center; gap: 10px; margin-bottom: 6px; }
.wave-editor .we-play { min-width: 42px; }
.wave-editor .we-hint { margin: 6px 0 4px; }
.wave-editor .we-sel { flex-wrap: wrap; gap: 10px; align-items: flex-end; }
.wave-editor .we-fld { display: flex; flex-direction: column; gap: 4px; font-size: 13px; }
.wave-editor .we-zones-h { font-size: 14px; margin: 12px 0 4px; }
.wave-editor .we-zone { align-items: center; gap: 8px; padding: 4px 0; border-top: 1px solid var(--line); }
.wave-editor .we-chip {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; border-radius: 6px; color: #fff; font-weight: 700; font-size: 12px; flex: none;
}
.wave-editor .we-err { margin: 6px 0; }
.wave-editor .we-vad { align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 8px; }
/* inline per-zone edit slider (zones adjustable after the fact, 2026-07-17) */
.we-zone-edit { flex-direction: row !important; align-items: center; gap: 6px; }
.we-zone-edit input[type=range] { width: 110px; }
/* recordings shelf under the mic button (2026-07-17) */
.we-shelf { margin-top: 10px; }
.we-shelf .we-zone { flex-wrap: wrap; }
/* added-audio tracks (2026-07-17): each take is its own sound bar under the main
   waveform — drag on the lane selects a part, the row below places it */
.cb-track { border: 1px solid var(--line); border-radius: 8px; padding: 6px 12px; margin: 8px 0; background: var(--paper); }
.cb-track-lane { border: 1px solid var(--line); border-radius: 6px; overflow: hidden; background: color-mix(in srgb, var(--accent2) 5%, var(--paper)); cursor: crosshair; }
.cb-track-lane canvas { display: block; width: 100%; }
.cb-track .row { margin: 6px 0 0; flex-wrap: wrap; gap: 8px; align-items: center; }
.cb-track p.meta { margin: 6px 0 0; font-size: 12px; }
/* compact tracks (Fikret's video 3:57): a closed track is one thin head line;
   ▸/▾ (or a double click on the head) folds the lane + controls open/shut */
.cb-track .cb-track-body { display: none; }
.cb-track.open .cb-track-body { display: block; }
.cb-track > .row:first-child { margin: 0; }
/* result waveform under the player (2026-07-17) */
/* a strip-click on the band highlights the matching placed-piece row */
.we-piece-flash { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 6px; }

/* ---- floating "?" hint box (2026-07-17, Fikret's mime video: opening a hint
   pushed the page down — now it is a compact fixed box, zero reflow) ---- */
#cbHintPop {
  position: fixed; z-index: 70; max-width: 300px;
  background: var(--paper); border: 1px solid var(--line); border-radius: 8px;
  box-shadow: 0 2px 6px var(--shadow-sm), 0 12px 32px -12px var(--shadow-lg);
  padding: 8px 11px; font-size: 12.5px; line-height: 1.45; color: var(--muted);
  white-space: pre-line; /* merged hints separate their topics with a blank line */
}
/* the bigger help panels float the same way when opened (any .help-panel) */
.help-pop {
  position: fixed; z-index: 70; margin: 0;
  width: min(440px, calc(100vw - 16px)); max-height: 60vh; overflow: auto;
  box-shadow: 0 2px 6px var(--shadow-sm), 0 12px 32px -12px var(--shadow-lg);
}

/* ---- studio layout (CBCOM Audio Mixer, Fikret's video reviews 2026-07-17:
   "we maken een app, geen tool" → workspace at the very top, extra wide; round
   2: no big website card but loose ISLANDS, bands stacked tightly) */
/* No dedicated ad column any more (2026-07-20: the ad moved to the shared, fixed-
   position .ad-rail in _Layout — see site.css's "the one ad slot" block) — the
   studio simply gets its full 1400px of workspace, always, ad-free plan or not. */
.wrap-studio { max-width: 1400px; }
/* the studio drops the .tool card chrome — the islands ARE the surfaces */
.tool.studio { background: transparent; border: 0; box-shadow: none; padding: 0; overflow: visible; }
.tool.studio::before { display: none; }
.tool.studio h1.studio-h1 { font-size: 20px; margin: 4px 0 8px; }
.mx-island { margin: 0 0 8px; align-items: center; gap: 12px; }
.mx-island > .row { margin: 0; }
/* compact source island instead of the big drop box */
.drop.mini { padding: 10px 16px; display: inline-block; text-align: start; background: var(--paper); }
.drop.mini strong { font-size: 14px; }
/* the band stack: tight full-width sound bars, straight below each other */
.mx-band { margin: 6px 0; }
.mx-band .wave-editor { margin-top: 0; }
.mx-band .we-top { margin-bottom: 2px; }
/* the highlighted band receives edits/placements (shown with >1 band) */
.mx-band.active .we-canvas-wrap { border-color: var(--accent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 22%, transparent); }
/* filename in small contrast letters ON the bar itself (end of the bar) */
.we-bandlabel {
  position: absolute; top: 4px; right: 6px; display: inline-flex; align-items: center; gap: 6px;
  background: color-mix(in srgb, var(--ink) 78%, transparent); color: var(--paper);
  font-family: var(--mono); font-size: 11px; padding: 2px 4px 2px 8px; border-radius: 6px;
}
.we-bandlabel .we-bandx {
  background: none; border: 0; color: inherit; cursor: pointer; font-size: 11px; padding: 0 4px; line-height: 1;
}
.we-bandlabel .we-bandx:hover { color: var(--accent); }
/* M/S toggles on the bar (v10, classic mixer) — lit = active */
.we-bandlabel .we-bandbtn { font-weight: 700; border-radius: 4px; padding: 1px 5px; opacity: .75; }
.we-bandlabel .we-bandbtn.on { background: var(--accent); color: #fff; opacity: 1; }
/* loop toggle next to ▶ (v10) — lit when looping */
.wave-editor .we-loop.on { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 18%, var(--paper)); }
/* active transport states (v13): playing ▶, and the ⏪/⏩ shuttle showing its speed */
.wave-editor .we-play.on, .wave-editor .we-shuttle.on,
#vsPlay.on, #vsFfw.on, #vsFbw.on { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 16%, var(--paper)); }
/* ---- islands: loose panels, each closable, back via the Panels menu ---- */
.mx-islands { display: flex; flex-wrap: wrap; gap: 12px; align-items: flex-start; margin-top: 10px; }

/* video studio: the picture is the centre of the program, so the stage gets the
   width and the panels sit underneath it (same .isl framework as audio) */
/* The stage is resizable like the islands (drag the bottom-right corner) so the
   picture can be shrunk out of the way while working in the panels; the ⤢
   button in the transport puts it back to full width. The canvas scales INSIDE
   whatever size the stage has — never clipped (Fikret, 2026-07-19). */
.vs-stage { display: flex; justify-content: center; align-items: center; background: #000; border-radius: 12px; overflow: hidden; resize: both; min-width: 240px; min-height: 135px; max-width: 100%; }
/* Shrinking the stage frees the space NEXT to it: the islands (camera panel,
   record button) flow up beside the picture instead of staying below the fold.
   Full-width stage → islands simply wrap underneath, the old layout.
   display:contents — the islands are FREE flex items of .vs-work, not a pinned
   right-hand column (Fikret: "vastgepind... ze moeten vrij in te delen zijn"):
   they flow beside the stage, wrap into full rows below, and stay individually
   draggable/resizable. */
.vs-work { display: flex; flex-wrap: wrap; gap: 14px; align-items: flex-start; }
.vs-work .vs-main { flex: 0 1 auto; min-width: 240px; max-width: 100%; }
.vs-work .mx-islands { display: contents; }
/* The export buttons must NEVER scroll away inside a resized island — a
   scrolling list is fine, a vanishing button is not (Fikret's "export knop is
   er niet meer": scrolled above the island's own scrollbar). */
.vs-out-actions { position: sticky; top: 0; background: var(--paper); z-index: 2; padding-bottom: 6px; }
/* Every format shows as a viewport-bounded miniature (Fikret 2026-07-21: a phone or
   square format used to blow up to full pixel size — 720×1280 — and overflow the page
   instead of scaling down like a small phone next to a 17" screen). A vh max-height
   guarantees the scale-down for ANY aspect ratio, independent of the parent's height. */
.vs-stage canvas { max-width: 100%; max-height: 78vh; width: auto; height: auto; display: block; cursor: move; touch-action: none; }
/* the ⤢ button toggles this compact view so the stage can be shrunk back with one click */
.vs-stage.vs-compact canvas { max-height: 44vh; }
/* live stage-record button while rolling: unmistakably red so you never leave it running */
#vsRecStage.rec-on { color: #fff; background: #d32f2f; border-color: #d32f2f; }
/* the camera/screen preview in the record panel: scale with the island instead
   of clipping to a quarter of the picture when the island is made smaller */
.vs-cam { max-width: 100%; height: auto; display: block; border-radius: 8px; }
/* one picture at a time: while the live feed owns the MAIN stage the panel
   preview moves off-screen (NOT display:none — the canvas must keep painting
   for captureStream). It returns the moment a clip takes the stage. */
.vs-cam-off { position: absolute; left: -10000px; top: 0; }
.vs-row { border: 1px solid var(--line); border-radius: 10px; padding: 6px 8px; margin-bottom: 6px; }
.vs-row .pfield { margin: 4px 0 0; }
/* Edit island: knob-EQ far LEFT as a vertical column, motors to its right
   (Fikret round 6 — much more compact) */
.mx-edit-cols { display: flex; gap: 14px; align-items: flex-start; flex-wrap: wrap; }
.mx-edit-left { flex: 1 1 320px; min-width: 0; }
.mx-eqcorner {
  flex: 0 0 auto; text-align: center; padding: 8px 10px;
  border: 1px solid var(--line); border-radius: 10px;
  background: color-mix(in srgb, var(--accent2) 5%, var(--paper));
}
.mx-knob-col { display: flex; flex-direction: column; gap: 8px; align-items: center; margin-top: 4px; }
/* anti-jitter (Fikret round 6): the value label has a FIXED width and the slider
   a fixed length, so 100→99 or a minus sign can never push anything around */
.mx-val { display: inline-block; width: 52px; flex: none; font-family: var(--mono); font-size: 11px; text-align: end; }
.mx-motor input[type=range], #mxFxList input[type=range] { width: 150px; flex: none; }
.mx-motor .meta { min-width: 92px; flex: none; }
.mx-knob { display: flex; flex-direction: column; align-items: center; width: 46px; }
.mx-knob-dial {
  width: 36px; height: 36px; border-radius: 50%; cursor: ns-resize; touch-action: none;
  border: 2px solid var(--line); position: relative;
  background: radial-gradient(circle at 35% 30%, color-mix(in srgb, var(--paper) 70%, #fff), var(--paper));
}
.mx-knob-dial::after {
  content: ""; position: absolute; left: 50%; top: 3px; width: 2px; height: 11px;
  background: var(--accent); border-radius: 2px;
  transform-origin: 50% 15px; transform: translateX(-50%) rotate(var(--rot, 0deg));
}
.mx-knob-dial:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.mx-knob-cap { font-size: 11px; font-weight: 700; margin-top: 3px; }
.mx-knob-val { font-size: 10px; color: var(--muted); font-family: var(--mono); }
/* player + library rows and the synth keyboard */
.mx-play-row { gap: 6px; margin: 4px 0; }
.mx-play-row .ghost { padding: 4px 9px; font-size: 12px; }
.mx-play-row.on .ghost:first-child { border-color: var(--accent); color: var(--accent-ink); }
.mx-playlist { max-height: 180px; overflow-y: auto; }
.mx-keys { display: flex; gap: 3px; flex-wrap: wrap; margin: 8px 0 4px; }
.mx-key { min-width: 30px; padding: 12px 4px 6px; font-size: 11px; }
.mx-key.sharp { background: color-mix(in srgb, var(--ink) 82%, var(--paper)); color: var(--paper); }
.mx-seq { min-height: 18px; font-family: var(--mono); font-size: 12px; word-break: break-word; }
.isl {
  background: var(--paper); border: 1px solid var(--line); border-radius: 10px;
  box-shadow: 0 1px 2px var(--shadow-sm), 0 10px 26px -18px var(--shadow-lg);
  padding: 8px 12px 10px; flex: 0 0 auto; min-width: 220px; max-width: 100%;
  /* v11: every panel is user-resizable (native grip, bottom corner); a panel
     made smaller than its content scrolls — the 🗖 button jumps to full size */
  resize: both; overflow: auto; min-height: 40px;
}
.isl-wide { flex: 0 0 auto; } /* v11: no special width — all panels default alike */
.isl-h { display: flex; align-items: center; gap: 6px; margin-bottom: 2px; cursor: grab; user-select: none; touch-action: none; }
/* the title takes the free space so ?/🗖/✕ always sit TOGETHER at the end
   (v11 fix: space-between spread them across the whole width) */
.isl-h > span:first-child { font-weight: 700; font-size: 13px; flex: 1 1 auto; min-width: 0; }
/* a panel being dragged to a new spot (grab it by its title bar) */
.isl-dragging { opacity: .75; outline: 2px dashed var(--accent); outline-offset: 2px; }
.isl-x { padding: 2px 8px; font-size: 12px; }
.isl-mm { font-size: 11px; } /* 🗖 grow-to-content / 🗕 back-to-own-size (v11) */
/* ---- polish round (2026-07-18): three button weights, not one grey wall.
   .primary = the action this panel is FOR, .danger = removes audio.
   Both keep the ghost shape, so the family stays recognisable. */
.ghost.primary {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 14%, var(--paper));
  color: var(--ink); font-weight: 700;
}
.ghost.primary:hover { background: color-mix(in srgb, var(--accent) 24%, var(--paper)); }
.ghost.danger { color: color-mix(in srgb, #d33 70%, var(--ink)); }
.ghost.danger:hover { border-color: #d33; background: color-mix(in srgb, #d33 10%, var(--paper)); }
/* an empty panel says so in one dim line instead of being a blank box */
.isl-b[data-empty]:empty::before {
  content: attr(data-empty);
  display: block; padding: 6px 2px; font-size: 12px; color: var(--muted); font-style: italic;
}
/* v12: the record-the-mix button turns red while a take is running */
#mxRecOut.rec-on { border-color: #d33; color: #d33; font-weight: 700; font-family: var(--mono); }
/* ---- v13: Winamp-style player deck. Deliberately its OWN retro skin with
   fixed colours (the CodeQuest precedent: a product identity, not site chrome) */
.mx-wamp-lcd { background: #0a1608; border: 1px solid #1d3a18; border-radius: 6px; padding: 6px 10px; font-family: var(--mono); color: #7dff6e; }
.mx-wamp-title { font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mx-wamp-time { font-size: 11px; opacity: .8; }
.mx-wamp-row { gap: 6px; align-items: flex-end; flex-wrap: wrap; }
.mx-wamp-btn { padding: 4px 10px; font-size: 13px; }
.mx-wamp-seek { width: 100%; margin: 6px 0 2px; }
.mx-wamp-eq { font-size: 11px; }
.mx-wamp-eq input[type=range] { width: 64px; }
/* the popped-out player floats above the page and drags anywhere */
.isl-float { position: fixed; z-index: 30; box-shadow: 0 6px 14px var(--shadow-sm), 0 28px 70px -28px var(--shadow-lg); }
.isl-fb { padding: 2px 8px; font-size: 11px; }
/* v13: library categories (collapsible) + loop badge + synth key caps */
.mx-lib-cat { display: block; width: 100%; text-align: start; font-weight: 700; margin-top: 6px; }
.mx-lib-items { margin: 2px 0 4px; }
.mx-lib-loop { font-size: 12px; }
#isl-library .isl-b { max-height: 360px; overflow-y: auto; }
.mx-key small { display: block; font-size: 9px; opacity: .65; line-height: 1; min-height: 9px; }
.mx-key.on { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 18%, var(--paper)); }
/* ---- voice changer (2026-07-18): preset tiles, icon + word (never colour alone) */
.vc-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 8px; width: 100%; }
.vc-preset { display: flex; align-items: center; gap: 8px; text-align: start; padding: 8px 10px; }
.vc-preset .vc-ic { font-size: 18px; line-height: 1; }
.vc-preset.on { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 14%, var(--paper)); font-weight: 700; }
/* the "add audio file" button stays: with the drop box gone (2026-07-18) it IS
   the file loader here — on a page without a main file it feeds the main input */
.isl-h .help-btn { padding: 0 7px; font-size: 12px; } /* the "?" after the title */
.isl-b .row { margin: 8px 0; }
.mx-motor { gap: 8px; align-items: center; }
.mx-motor .meta { min-width: 84px; }
/* Panels menu chips (closed islands come back from here) */
.mx-isl-menu { margin: 8px 0 0; gap: 6px; align-items: center; }
.isl-chip { font-size: 12px; padding: 4px 10px; opacity: .55; }
.isl-chip.on { opacity: 1; border-color: var(--accent); }
.isl-menu-btn { font-size: 15px; padding: 4px 9px; }
.mx-isl-menu.chips-folded .isl-chip { display: none; }
/* Sounds / Recordings: small compact lists (quarter-B5 feel) — a scrolling LIST
   is fine, a disappearing button is not (the standing panel rule) */
/* Detection island stays COMPACT in use (Fikret round 9: it tripled in size
   once the status sentence appeared and shoved the other panels around) —
   status lines are small blocks, buttons wrap, the voice list runs vertically.
   (v11: the old max-width caps are gone — panels are user-resizable and get a
   340px DEFAULT width from JS instead, so growing past it stays possible.) */
#isl-detect .isl-b { font-size: 12px; }
#isl-detect .ghost { padding: 4px 9px; font-size: 12px; }
.mx-det-st { display: block; font-size: 12px; color: var(--muted); margin: 5px 0 2px; }
.mx-det-sens { display: flex; align-items: center; gap: 6px; font-size: 12px; margin: 6px 0 0; cursor: pointer; }
.mx-det-sens input { width: auto; margin: 0; }
.mx-det-acts { flex-wrap: wrap; gap: 6px; }
.mx-spk { border-top: 1px dashed var(--line); padding-top: 6px; margin-top: 8px; }
.mx-spk .row { margin: 4px 0; gap: 6px; align-items: center; }
.mx-spk .meta { flex: 1 1 auto; }
.mx-spk input[type=range] { width: 96px; }
.mx-spk select { font-size: 12px; padding: 3px 6px; width: auto; }
/* the FX-block list may grow (voice edits add one block per segment) —
   a scrolling LIST is fine, a disappearing button is not */
#mxFxList { max-height: 220px; overflow-y: auto; }
#isl-sounds .isl-b, #isl-records .isl-b { max-height: 240px; overflow-y: auto; font-size: 12px; }
#isl-sounds .cb-track, #isl-records .cb-track { padding: 3px 8px; margin: 5px 0; }
#isl-sounds .cb-track .meta, #isl-records .cb-track .meta { font-size: 12px; }
#isl-sounds .cb-track .ghost, #isl-records .cb-track .ghost { padding: 3px 8px; font-size: 12px; }
.we-static { border: 1px solid var(--line); border-radius: 8px; overflow: hidden; margin: 8px 0; background: color-mix(in srgb, var(--accent2) 4%, var(--paper)); }
.we-static canvas { display: block; width: 100%; }

/* ---- /pricing page ---- */
/* regional-pricing note (world tiers, 2026-07-16) — only rendered for tier 2/3 visitors */
.geo-note { color: var(--accent2); font-weight: 600; }
.coming-soon-banner {
  background: color-mix(in srgb, var(--accent2) 10%, var(--paper));
  border-color: color-mix(in srgb, var(--accent2) 35%, var(--line));
}
.price-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 14px; margin-top: 6px; }
.price-card {
  border: 1px solid var(--line); border-radius: 10px; padding: 16px; background: var(--paper);
  text-decoration: none; color: inherit; display: block; transition: border-color .15s, transform .15s;
}
a.price-card:hover { border-color: var(--accent); transform: translateY(-2px); }
.price-card h3 { margin: 0 0 10px; font-size: 15px; }
.price-card .examples { color: var(--muted); font-size: 12.5px; margin: 8px 0 0; }
.price-card .big-price { display: block; font-size: 26px; margin: 4px 0; }
.price-card.featured-card { border-color: var(--accent); box-shadow: 0 6px 18px -10px color-mix(in srgb, var(--accent) 60%, transparent); }
.badge-free, .badge-owned {
  display: inline-block; font-size: 11px; font-weight: 600; letter-spacing: .03em; text-transform: uppercase;
  color: var(--ok); background: color-mix(in srgb, var(--ok) 14%, transparent); border-radius: 6px; padding: 3px 8px; margin-bottom: 8px;
}
.badge-owned { text-transform: none; letter-spacing: 0; }
.badge-save {
  display: inline-block; font-size: 11px; font-weight: 600; color: var(--accent-ink);
  background: color-mix(in srgb, var(--accent) 18%, transparent); border-radius: 6px; padding: 2px 7px; margin-inline-end: 6px;
}
.price-card .durations { display: flex; gap: 8px; flex-wrap: wrap; }
.price-card .duration {
  flex: 1 1 0; min-width: 78px; text-align: center; border: 1px solid var(--line); border-radius: 8px; padding: 8px 6px;
}
.price-card .duration b { display: block; font-size: 16px; }
.price-card .duration span { display: block; font-size: 11px; color: var(--muted); }
.price-card .duration.featured { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, transparent); }
.price-card .duration span.badge-save { display: inline-block; color: var(--accent-ink); }
/* Day pass link, made a visible pill instead of plain fine-print text (Fikret
   2026-07-20: it existed but was too easy to scroll past). */
.daypass-link {
  display: block; margin-top: 10px; padding: 7px 10px; text-align: center;
  font-size: 12.5px; font-weight: 600; text-decoration: none; color: var(--accent-ink);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 35%, var(--line)); border-radius: 8px;
  transition: background .12s ease;
}
.daypass-link:hover { background: color-mix(in srgb, var(--accent) 20%, transparent); }
.combo-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 12px; margin-top: 6px; }
.combo-card { border: 1px solid var(--line); border-radius: 10px; padding: 14px; background: var(--paper); text-align: center; }
.combo-pair { font-size: 13px; color: var(--muted); margin-bottom: 8px; }
.combo-pair .plus { color: var(--accent-ink); font-weight: 700; margin: 0 4px; }
.combo-price s { color: var(--muted); font-size: 13px; margin-inline-end: 6px; }
.combo-price b { font-size: 19px; }
.combo-price span { color: var(--muted); font-size: 12px; }

/* ---- safety warning (machining calculators) ---- */
.safety-warning {
  display: flex; gap: 10px; align-items: flex-start; margin-top: 14px;
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 45%, var(--line));
  border-radius: 8px; padding: 12px 14px;
}
.safety-warning span { flex: none; font-size: 17px; line-height: 1.4; }
.safety-warning p { margin: 0; color: var(--ink); font-size: 13px; max-width: none; }

/* Before/after dimensions table (shrinkage scaler). */
.scale-table { border-collapse: collapse; margin-top: 6px; font-size: 13px; }
.scale-table td { border: 1px solid var(--line); padding: 4px 12px; text-align: right; }
.scale-table td:first-child { text-align: left; border: 0; padding-left: 0; }
.scale-table tr:first-child td { border: 0; color: var(--muted); font-size: 11px; text-align: right; }

/* Two coordinate inputs sharing one panel field row (DXF editor). */
.editor-panel label.fld input[type=number] { flex: 1 1 0; min-width: 0; }

/* ---- catalog grid (used on home + "more tools" sections) ---- */
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 12px; }
.card {
  border: 1px solid var(--line); border-radius: 8px; padding: 12px 13px; background: var(--paper); cursor: pointer;
  text-align: left; font: inherit; text-decoration: none; color: inherit; display: block;
  transition: transform .12s ease, box-shadow .12s ease, border-color .12s ease;
}
.card:hover { border-color: var(--accent); transform: translateY(-2px); box-shadow: 0 8px 18px -12px var(--shadow-lg); }
.card .t { font-weight: 600; font-size: 14px; }
.card .d { color: var(--muted); font-size: 12.5px; margin-top: 2px; }
.card .tag { display: inline-block; margin-top: 8px; font-size: 10.5px; letter-spacing: .08em; text-transform: uppercase; color: #93a0af; }
.card.soon { opacity: .72; cursor: default; }

/* ---- homepage hero + segments ---- */
/* richer than a plain card — reinforces "this is a product" on the very first thing seen */
.hero {
  position: relative; overflow: visible;
  background: linear-gradient(160deg, color-mix(in srgb, var(--accent) 8%, var(--paper)), color-mix(in srgb, var(--accent2) 6%, var(--paper)) 75%);
}
.hero h1 { max-width: 24ch; }
.hero .lede { max-width: 56ch; }
/* The big logo is a transparent PNG since 2026-07-13 (Fikret's square version)
   and floats directly on BOTH themes — Fikret checked it on a dark surface
   himself ("het is niet zo erg als je denkt") and dropped the dark-mode badge. */
:root { --biglogo-bg: transparent; }
/* 200->300px (2026-07-21, Fikret: +50% on the mainpage) — the brand-card version
   elsewhere on every tool page keeps its own, larger 420px size unchanged. It also
   gently floats now (the "flying" feel Fikret asked for); disabled for reduced-motion. */
.hero-logo { display: block; max-width: 300px; width: 100%; height: auto; margin: 0 auto 14px; padding: 10px; box-sizing: border-box; background: var(--biglogo-bg); border-radius: 12px; animation: cb-float 5.5s ease-in-out infinite; }
@keyframes cb-float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-8px); } }

/* ---- interactive hero accordion (2026-07-21, Fikret's "flying info bar") ----
   The hero blurb sits fixed on the left and ALWAYS shows its full content — it never
   reacts to hover, and (crucially) it defines the row height so nothing ever moves
   vertically. The three feature panels share the rest; hovering one widens it and
   reveals its text, taking room only from its two siblings. Their descriptions are
   absolutely positioned, so revealing one can NEVER change the row height — the page
   below stays perfectly still (Fikret: "hou ze in toom"). Touch/narrow → plain stack. */
.hero-accordion { display: flex; gap: 10px; margin-top: 4px; align-items: stretch; }
.hp {
  position: relative; display: flex; flex-direction: column; gap: 6px;
  min-width: 0; overflow: hidden;
  padding: 18px; border-radius: 14px; text-align: left;
  border: 1px solid var(--line);
  background: color-mix(in srgb, var(--accent) 5%, var(--paper));
  transition: flex-grow .4s cubic-bezier(.2, .7, .2, 1), box-shadow .25s ease;
}
/* the hero tile: fixed width, full content always, inert to hover */
.hp-hero { flex: 0 0 42%; background: linear-gradient(160deg, color-mix(in srgb, var(--accent) 12%, var(--paper)), color-mix(in srgb, var(--accent2) 8%, var(--paper)) 80%); }
/* the three feature tiles share the remaining width; the hovered one grows, its two
   siblings shrink — the hero and everything below are untouched */
.hp-f1, .hp-f2, .hp-f3 { flex: 1 1 0; }
.hp-f1:hover, .hp-f2:hover, .hp-f3:hover { flex-grow: 2.6; box-shadow: 0 12px 34px -14px var(--shadow-lg); }
.hp-head { display: flex; gap: 12px; align-items: flex-start; }
.hp-icon {
  flex: none; width: 44px; height: 44px; border-radius: 11px;
  display: flex; align-items: center; justify-content: center;
  color: var(--accent-ink); background: color-mix(in srgb, var(--accent) 18%, var(--paper));
}
.hp-icon svg { width: 24px; height: 24px; }
.hp-f2 .hp-icon { color: var(--accent2-ink); background: color-mix(in srgb, var(--accent2) 18%, var(--paper)); }
.hp-f3 .hp-icon { color: var(--accent3-ink); background: color-mix(in srgb, var(--accent3) 18%, var(--paper)); }
.hp .eyebrow { margin: 0; }
.hp h1 { font-size: clamp(20px, 2.3vw, 30px); margin: 3px 0 0; line-height: 1.15; }
.hp h2 { font-size: 16.5px; margin: 8px 0 0; }
/* hero description: normal flow, always visible — it sets the constant row height */
.hp-hero .hp-desc .lede { margin: 0; }
/* feature descriptions: absolutely positioned so they add ZERO height; fade in only
   when that tile is hovered. Because they never affect layout, the row can't grow. */
.hp-f1 .hp-desc, .hp-f2 .hp-desc, .hp-f3 .hp-desc {
  position: absolute; left: 18px; right: 14px; top: 76px;
  opacity: 0; transition: opacity .25s ease; pointer-events: none;
}
.hp-f1:hover .hp-desc, .hp-f2:hover .hp-desc, .hp-f3:hover .hp-desc { opacity: 1; }
.hp-desc p { margin: 0; color: var(--muted); font-size: 14px; }
.hero-badge {
  display: inline-flex; align-items: center; gap: 6px; align-self: flex-start;
  margin-top: 14px; padding: 7px 15px; border-radius: 999px;
  font-weight: 700; font-size: 14px; color: #fff;
  background: linear-gradient(90deg, var(--accent), var(--accent2));
  box-shadow: 0 8px 20px -8px var(--accent);
  animation: cb-pulse 2.4s ease-in-out infinite;
}
@keyframes cb-pulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.06); } }
/* Touch devices (no hover) and phones: plain readable stack — every panel fully open,
   descriptions back in normal flow so nothing is clipped. */
@media (hover: none), (max-width: 720px) {
  .hero-accordion { flex-direction: column; }
  .hp-hero, .hp-f1, .hp-f2, .hp-f3 { flex: 1 1 auto; }
  .hp-f1 .hp-desc, .hp-f2 .hp-desc, .hp-f3 .hp-desc { position: static; opacity: 1 !important; margin-top: 8px; }
}
@media (prefers-reduced-motion: reduce) {
  .hero-logo, .hero-badge { animation: none; }
  .hp { transition: none; }
}

/* ---- quick-launch bar (2026-07-21, Fikret's "flying info bar") ----
   A slim sticky bar of studio + category chips. Hidden while the hero is in view;
   flies in when you scroll back UP past the hero, and gets out of the way when you
   scroll DOWN — so tools/software stay one click away without ever being in the way.
   Sits just under the sticky header (JS sets its `top` to the header height). */
.quicklaunch {
  position: fixed; left: 0; right: 0; z-index: 19;
  background: var(--header-bg); backdrop-filter: blur(6px);
  border-bottom: 1px solid var(--line);
  box-shadow: 0 10px 24px -16px var(--shadow-lg);
  transform: translateY(-140%);
  transition: transform .32s cubic-bezier(.2, .7, .2, 1);
  will-change: transform;
}
.quicklaunch.show { transform: translateY(0); }
.ql-inner { max-width: 1180px; margin: 0 auto; display: flex; gap: 8px; align-items: center; padding: 8px 12px; overflow-x: auto; scrollbar-width: thin; }
.ql-chip {
  flex: none; display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 11px; border-radius: 999px; border: 1px solid var(--line);
  background: var(--paper); color: var(--ink); text-decoration: none;
  font-size: 13px; font-weight: 600; white-space: nowrap;
  transition: transform .15s ease, box-shadow .15s ease, border-color .15s ease;
}
.ql-chip:hover { transform: translateY(-1px); border-color: color-mix(in srgb, var(--accent) 50%, var(--line)); box-shadow: 0 6px 14px -8px var(--shadow-lg); }
.ql-chip .ql-i { font-size: 15px; line-height: 1; }
.ql-studio { border-color: color-mix(in srgb, var(--accent) 40%, var(--line)); background: color-mix(in srgb, var(--accent) 9%, var(--paper)); }
.ql-sep { flex: none; width: 1px; align-self: stretch; background: var(--line); margin: 3px 2px; }
@media (max-width: 700px) {
  .ql-inner { padding: 6px 8px; gap: 6px; }
  .ql-chip { font-size: 12px; padding: 5px 9px; }
}
@media (prefers-reduced-motion: reduce) { .quicklaunch { transition: none; } }

/* ---- help "vraagbaak" widget (2026-07-21) ----
   Bottom-LEFT on purpose: the ad rail lives on the right, so the launcher never
   overlaps an ad slot (AdSense accidental-click safety). */
.hb-launch {
  position: fixed; left: 18px; bottom: 18px; z-index: 30;
  width: 52px; height: 52px; border-radius: 50%; border: 1px solid var(--line);
  background: linear-gradient(160deg, var(--accent), var(--accent2)); color: #fff;
  font-size: 23px; line-height: 1; cursor: pointer; padding: 0;
  box-shadow: 0 10px 26px -10px var(--shadow-lg); transition: transform .15s ease, box-shadow .2s ease;
}
.hb-launch:hover { transform: translateY(-2px); box-shadow: 0 14px 32px -12px var(--shadow-lg); }
.hb-panel {
  position: fixed; left: 18px; bottom: 80px; z-index: 39;
  width: min(360px, calc(100vw - 24px)); max-height: min(70vh, 560px);
  display: none; flex-direction: column; overflow: hidden;
  background: var(--paper); border: 1px solid var(--line); border-radius: 14px;
  box-shadow: 0 18px 50px -20px var(--shadow-lg), 0 6px 16px -8px var(--shadow-sm);
}
.hb-panel.open { display: flex; }
.hb-head { display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 12px 14px; font-weight: 700; color: #fff; background: linear-gradient(90deg, var(--accent), var(--accent2)); }
.hb-x { background: none; border: 0; color: #fff; font-size: 22px; line-height: 1; cursor: pointer; padding: 0 4px; }
.hb-body { padding: 12px 14px; overflow-y: auto; flex: 1; }
.hb-intro { margin: 0 0 10px; color: var(--muted); font-size: 13.5px; }
.hb-sugg { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 10px; }
.hb-chip { border: 1px solid var(--line); background: var(--paper); color: var(--ink);
  border-radius: 999px; padding: 5px 11px; font-size: 12.5px; cursor: pointer; text-align: start; }
.hb-chip:hover { border-color: color-mix(in srgb, var(--accent) 50%, var(--line)); }
.hb-answer .hb-a { margin: 0 0 8px; font-size: 14px; color: var(--ink); line-height: 1.5; }
.hb-answer .hb-th { margin: 8px 0 4px; font-weight: 700; font-size: 13px; }
.hb-tools { margin: 0; padding-inline-start: 18px; }
.hb-tools li { margin: 3px 0; font-size: 14px; }
.hb-form { display: flex; gap: 6px; padding: 10px 12px; border-top: 1px solid var(--line); }
.hb-input { flex: 1; min-width: 0; }
.hb-send { flex: none; padding: 0 12px; }
@media (max-width: 700px) {
  .hb-launch { width: 46px; height: 46px; font-size: 21px; left: 12px; bottom: 12px; }
  .hb-panel { left: 12px; right: 12px; bottom: 66px; width: auto; }
}
.brand-card { text-align: center; }
.brand-card img { max-width: 420px; width: 100%; height: auto; padding: 10px; box-sizing: border-box; background: var(--biglogo-bg); border-radius: 12px; }

.segments { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
.segment { text-align: left; }
.segment h2 { font-size: 17px; margin: 4px 0 6px; }
.segment p { color: var(--muted); font-size: 14px; margin: 0 0 14px; }
.segment-icon {
  width: 40px; height: 40px; border-radius: 10px; display: flex; align-items: center; justify-content: center;
  color: var(--accent-ink); background: color-mix(in srgb, var(--accent) 16%, var(--paper));
}
.segment:nth-child(2) .segment-icon { color: var(--accent2-ink); background: color-mix(in srgb, var(--accent2) 16%, var(--paper)); }
.segment:nth-child(3) .segment-icon { color: var(--accent3-ink); background: color-mix(in srgb, var(--accent3) 16%, var(--paper)); }
.segment-icon svg { width: 21px; height: 21px; }

@media (max-width: 900px) {
  .segments { grid-template-columns: 1fr; }
}

/* homepage tool tiles — "LIT" pass (2026-07-12): each category gets its own color
   identity (icon badge + tinted section + tinted, left-accented cards) so scrolling
   through the homepage reads as moving through a designed product's sections, not a
   flat directory listing. Colors are moderate/professional, not neon — same shadow
   and radius language as every other card on the site (rule 3 homogeneity), only the
   hue changes per category. */
.cat-audio        { --cat: #7c5cbf; --cat-ink: #4a3380; }
.cat-video        { --cat: #c0524a; --cat-ink: #7a2f28; }
.cat-images       { --cat: var(--accent); --cat-ink: var(--accent-ink); }
.cat-pdf          { --cat: var(--accent2); --cat-ink: var(--accent2-ink); }
.cat-business     { --cat: #1f9e7c; --cat-ink: #0f5c46; }
.cat-cad          { --cat: #55708a; --cat-ink: #2e4155; }
.cat-dev          { --cat: #5a63c4; --cat-ink: #33397a; }
.cat-machining    { --cat: #a8672a; --cat-ink: #603a18; }
.cat-engineering  { --cat: #1f8fa3; --cat-ink: #0f4e59; }
:root[data-theme="dark"] .cat-audio       { --cat: #b09ee8; --cat-ink: #d8cff5; }
:root[data-theme="dark"] .cat-video       { --cat: #e2948c; --cat-ink: #f5d4d0; }
:root[data-theme="dark"] .cat-business    { --cat: #4dcda8; --cat-ink: #a8f0da; }
:root[data-theme="dark"] .cat-cad         { --cat: #9fb4c7; --cat-ink: #d3e0ea; }
:root[data-theme="dark"] .cat-dev         { --cat: #9ba3e8; --cat-ink: #d4d8f7; }
:root[data-theme="dark"] .cat-machining   { --cat: #d99b4f; --cat-ink: #f0cfa0; }
:root[data-theme="dark"] .cat-engineering { --cat: #5fc9dd; --cat-ink: #b8ecf5; }

.cat-icon {
  flex: none; width: 36px; height: 36px; border-radius: 10px; font-size: 18px;
  display: flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--cat, var(--accent)) 20%, var(--paper));
}
.tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 10px; }
.tile {
  display: block; padding: 12px 14px; border: 1px solid var(--line); border-radius: 8px;
  border-inline-start: 3px solid var(--cat, var(--accent));
  text-decoration: none; background: color-mix(in srgb, var(--cat, var(--accent)) 4%, var(--paper));
  transition: border-color .12s ease, transform .12s ease, box-shadow .12s ease, background .12s ease;
}
.tile:hover {
  border-color: var(--cat, var(--accent)); transform: translateY(-2px);
  background: color-mix(in srgb, var(--cat, var(--accent)) 9%, var(--paper));
  box-shadow: 0 10px 22px -12px color-mix(in srgb, var(--cat, var(--accent)) 55%, transparent);
}
.tile strong { display: block; color: var(--cat-ink, var(--ink)); font-size: 14.5px; margin-bottom: 2px; }
.tile span { color: var(--muted); font-size: 12.5px; line-height: 1.35; display: block; }
/* flagship tools (the CBCOM studios + the 2D CAD Drawpad) get a subtle "featured"
   highlight on the category tile grids (2026-07-21, Fikret): a full ring, a soft glow
   and a small ★ in the corner — noticeable but not loud. */
.tile.flagship {
  position: relative;
  border-color: var(--cat, var(--accent));
  background: color-mix(in srgb, var(--cat, var(--accent)) 10%, var(--paper));
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--cat, var(--accent)) 45%, transparent),
              0 8px 22px -14px color-mix(in srgb, var(--cat, var(--accent)) 60%, transparent);
}
.tile.flagship::after {
  content: "\2605"; position: absolute; top: 6px; inset-inline-end: 9px;
  font-size: 12px; line-height: 1; color: var(--cat, var(--accent)); opacity: .85;
}
.tile.flagship:hover { box-shadow: 0 12px 26px -12px color-mix(in srgb, var(--cat, var(--accent)) 60%, transparent); }

/* ---- homepage studio islands + category overview (2026-07-20 redesign) ----
   Replaces the old always-expanded 99-tile wall + on-page search: 3 richer studio
   cards, then 9 compact category cards, both target=_blank so a click never loses
   the homepage tab. Category cards reuse the .cat-* color tokens above (same family
   look as the /tools/{slug} pages' own .tile cards). */
.studios-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 16px; }
.studio-card { display: block; text-decoration: none; color: inherit; transition: transform .12s ease, box-shadow .12s ease; }
.studio-card:hover { transform: translateY(-3px); }
.studio-card .studio-icon { font-size: 34px; line-height: 1; margin-bottom: 8px; }
.studio-card h3 { margin: 0 0 6px; font-size: 17px; }
.studio-card p { margin: 0; color: var(--muted); font-size: 13.5px; }
.studio-card .newtab-hint, .cat-card .newtab-hint { display: block; margin-top: 10px; font-size: 11.5px; color: var(--muted); }

.cats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 14px; }
.cat-card {
  display: block; padding: 16px 16px 14px; border: 1px solid var(--line); border-radius: 10px;
  border-inline-start: 3px solid var(--cat, var(--accent));
  text-decoration: none; color: inherit;
  background: color-mix(in srgb, var(--cat, var(--accent)) 4%, var(--paper));
  transition: border-color .12s ease, transform .12s ease, box-shadow .12s ease, background .12s ease;
}
.cat-card:hover {
  border-color: var(--cat, var(--accent)); transform: translateY(-2px);
  background: color-mix(in srgb, var(--cat, var(--accent)) 9%, var(--paper));
  box-shadow: 0 10px 22px -12px color-mix(in srgb, var(--cat, var(--accent)) 55%, transparent);
}
.cat-card-top { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; }
.cat-card h3 { margin: 0; font-size: 15.5px; color: var(--cat-ink, var(--ink)); flex: 1; min-width: 0; }
.cat-card .cat-count { font-size: 11px; font-weight: 600; color: var(--muted); flex: none; }
.cat-card p { margin: 0; color: var(--muted); font-size: 12.5px; line-height: 1.4; }

/* Gallery vs Index view (Fikret 2026-07-12): the base .tile styles above ARE the compact
   "Index view" (his personal favorite); the data-view="gallery" overrides below give new
   visitors the spacious tile look with a pictogram per tool. The pre-paint script in
   _Layout defaults to gallery; the header toggle (homepage only) flips and remembers it. */
.tile .tile-icon { display: none; } /* .tile .tile-icon (0-2-0) so it outranks the generic `.tile span` block rule above */
:root[data-view="gallery"] .tiles { grid-template-columns: repeat(auto-fill, minmax(215px, 1fr)); gap: 16px; }
:root[data-view="gallery"] .tile {
  text-align: center; padding: 20px 16px 16px;
  border-inline-start: 1px solid var(--line);
  border-top: 3px solid var(--cat, var(--accent));
}
:root[data-view="gallery"] .tile-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 48px; height: 48px; margin: 0 auto 10px; border-radius: 13px;
  color: var(--cat-ink, var(--accent-ink));
  background: color-mix(in srgb, var(--cat, var(--accent)) 15%, var(--paper));
}
:root[data-view="gallery"] .tile-icon svg { width: 27px; height: 27px; }
:root[data-view="gallery"] .tile strong { font-size: 15px; margin-bottom: 4px; }
:root[data-view="gallery"] .tile:hover .tile-icon {
  background: color-mix(in srgb, var(--cat, var(--accent)) 26%, var(--paper));
}

/* "quick cards" — Fikret's iPhone-style panel trial (crypto page first, 2026-07-10);
   his design, recolored onto our tokens (accent2 replaces iOS-blue, bg replaces iOS-grey) */
.top-controls { display: flex; flex-wrap: wrap; gap: 16px; margin-bottom: 20px; align-items: stretch; }
.ios-card {
  background: var(--paper); border-radius: 16px; padding: 16px 20px;
  border: 1px solid var(--line);
  box-shadow: 0 4px 14px -6px color-mix(in srgb, var(--ink) 18%, transparent);
  display: flex; flex-direction: column; justify-content: center;
}
.ios-card h2, .ios-card .eyebrow-label {
  margin: 0 0 10px; font-size: 13px; font-weight: 600; color: var(--muted);
  text-transform: uppercase; letter-spacing: .5px;
}
.converter-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
/* .ios-input/.ios-select need no own rules anymore — their style became the
   site-wide input/select standard (see the global rules above) */
.ios-equals { font-size: 20px; color: var(--muted); font-weight: 500; margin: 0 4px; }
.ios-label { font-size: 15px; font-weight: 600; color: var(--ink); }

/* related tools block on tool pages */
.related h2 { font-size: 15px; margin: 0 0 10px; }
.related-links { display: flex; flex-wrap: wrap; gap: 8px; }
.related-links .ghost { font-size: 13px; padding: 6px 11px; }
.related-links .ghost.pick {
  border-color: var(--accent); color: var(--accent-ink);
  background: color-mix(in srgb, var(--accent) 10%, transparent);
}
.pick-star { color: var(--accent-ink); margin-inline-end: 4px; }

/* site-wide footer sitemap */
.sitemap { border-top: 1px solid var(--line); background: var(--paper); }
.sitemap-in {
  max-width: 1180px; margin: 0 auto; padding: 22px 18px;
  display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 16px;
}
.sitemap-col h3 { font-size: 12.5px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); margin: 0 0 8px; }
.sitemap-col ul { list-style: none; margin: 0; padding: 0; }
.sitemap-col li { margin: 0 0 5px; }
.sitemap-col a { color: var(--ink); text-decoration: none; font-size: 13px; }
.sitemap-col a:hover { color: var(--accent-ink); text-decoration: underline; }

footer { max-width: 1180px; margin: 0 auto; padding: 26px 18px 50px; color: var(--muted); font-size: 13px; border-top: 1px solid var(--line); }
footer a { color: var(--muted); text-decoration: none; margin-inline-end: 14px; }
footer a:hover { color: var(--ink); }
footer button.linklike { background: none; border: none; padding: 0; margin-inline-end: 14px; color: var(--muted); font: inherit; cursor: pointer; text-decoration: none; }
footer button.linklike:hover { color: var(--ink); }

/* ---- modal (custom, never alert()/confirm() — rule 12; one at a time — rule 5) ---- */
.veil { position: fixed; inset: 0; background: rgba(17, 24, 32, .5); display: none; align-items: center; justify-content: center; z-index: 40; padding: 18px; }
.veil.open { display: flex; }
.modal { background: var(--paper); border-radius: 12px; max-width: 440px; width: 100%; padding: 24px; }
.modal h3 { margin: 0 0 6px; }
.modal p { color: var(--muted); font-size: 14px; }
.close { float: right; border: none; background: none; font-size: 20px; cursor: pointer; color: var(--muted); }

/* ---- welcome popup (same .veil/.modal family, sized up for its content) ----
   Distinct tinted background + stronger shadow/border than plain .modal — at this
   size it needs to read unmistakably as a floating overlay, not another page card. */
.modal-lg {
  max-width: 720px; max-height: calc(100vh - 60px); overflow-y: auto;
  /* warm accent tint, not blue — the page canvas itself already has a cool blue-ish
     wash (--bg + accent2 glow), so a blue-tinted popup nearly matched it and still
     read as "part of the page" instead of a distinct overlay. */
  background: linear-gradient(165deg, color-mix(in srgb, var(--accent) 16%, var(--paper)), var(--paper) 60%);
  border: 1px solid color-mix(in srgb, var(--accent) 38%, var(--line));
  box-shadow: 0 28px 70px -18px var(--shadow-lg), 0 4px 14px var(--shadow-sm);
}
.modal-lg .eyebrow { margin: 0 0 8px; }
.modal-lg h3 { font-size: 22px; }
.welcome-risk {
  font-size: 13px; color: var(--muted); background: color-mix(in srgb, var(--accent) 8%, transparent);
  border: 1px solid var(--line); border-radius: 8px; padding: 10px 12px; margin: 10px 0;
}
.welcome-features { display: flex; flex-direction: column; gap: 9px; margin: 16px 0; }
.welcome-features div { display: flex; gap: 10px; align-items: flex-start; font-size: 14px; color: var(--ink); }
.welcome-features span { flex: none; font-size: 17px; line-height: 1.4; }
.welcome-cats { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px 18px; margin: 18px 0 6px; }
.welcome-cat h4 { margin: 0 0 2px; font-size: 13.5px; position: relative; padding-inline-start: 14px; }
.welcome-cat h4::before {
  content: ""; position: absolute; inset-inline-start: 0; top: 3px; bottom: 3px; width: 4px;
  border-radius: 2px; background: linear-gradient(180deg, var(--accent), var(--accent2));
}
.welcome-cat p { margin: 0; font-size: 12.5px; color: var(--muted); padding-inline-start: 14px; }
.welcome-closing { margin: 16px 0 4px; font-size: 14px; color: var(--ink); }
.welcome-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 14px; flex-wrap: wrap; }
@media (max-width: 560px) { .welcome-cats { grid-template-columns: 1fr; } }

/* ---- cookie consent banner ---- */
.consent { position: fixed; left: 0; right: 0; bottom: 0; z-index: 50; background: var(--paper); border-top: 1px solid var(--line); box-shadow: 0 -2px 12px var(--shadow-sm); }
.consent.hidden { display: none; }
.consent-in { max-width: 1180px; margin: 0 auto; padding: 16px 18px; display: flex; gap: 16px; align-items: center; flex-wrap: wrap; }
.consent-in p { margin: 0; color: var(--muted); font-size: 13.5px; flex: 1 1 320px; }
.consent-actions { display: flex; gap: 10px; flex: none; }

/* ---- language picker (flag button + Z-A menu, toggled in site.js) ---- */
.lang { position: relative; }
.lang-btn { display: inline-flex; align-items: center; padding: 8px 10px; }
.lang svg.flag { width: 20px; height: 14px; border-radius: 3px; box-shadow: 0 0 0 1px var(--line); display: block; flex: none; }
.lang-menu {
  position: absolute; inset-inline-end: 0; top: calc(100% + 8px); z-index: 60;
  margin: 0; padding: 6px; list-style: none; min-width: 178px;
  background: var(--paper); border: 1px solid var(--line); border-radius: 10px;
  box-shadow: 0 1px 2px var(--shadow-sm), 0 14px 38px -14px var(--shadow-lg);
}
.lang-menu a { display: flex; align-items: center; gap: 10px; padding: 7px 10px; border-radius: 7px; color: var(--ink); text-decoration: none; font-size: 14px; white-space: nowrap; }
.lang-menu a:hover { background: var(--bg); }
.lang-menu a[aria-current="true"] { background: var(--bg); font-weight: 600; }
