/* ================================================================
   CHECKLINK: GLOBAL STYLESHEET
   Page chrome and design tokens. Dark glassmorphism in the Stormberry
   Labs house style, Inter typography, orchid accent.

   CSP note: the page forbids inline styles (style-src 'self'), so every
   rule lives here. Setting element.style from JavaScript is still
   allowed and is the way to position things at runtime.
================================================================ */

/* ---- Design tokens ------------------------------------------------ */
:root {
  color-scheme: dark;

  /* Background palette: near-black with a violet cast */
  --bg-base:        #0c0a12;
  --bg-surface:     #15111d;
  --bg-card:        rgba(28, 21, 40, 0.72);
  --bg-card-hover:  rgba(40, 30, 58, 0.85);
  /* Opaque equivalent of --bg-card over --bg-base, for anything that
     cannot be translucent (canvas fills, contrast checks). */
  --bg-card-solid:  #181222;

  /* Accent: orchid. Chosen because no other Labs app uses it and it
     sits clear of the red, amber and green tiers below. */
  --accent-primary: #e879f9;   /* 7.4:1 on cards, 8.0:1 on the page */
  --accent-strong:  #d946ef;   /* 5.3:1 on cards */
  --accent-soft:    rgba(232, 121, 249, 0.14);
  --grad-primary:   linear-gradient(135deg, #f0abfc 0%, #d946ef 100%);
  --on-accent:      #0c0a12;   /* text on the accent: 5.7:1 at its darkest */

  /* Text, all at least WCAG AA (4.5:1) on --bg-base and on cards */
  --text-primary:   #f5f1fa;   /* 16.4:1 on cards */
  --text-secondary: #b9afcb;   /*  8.8:1 on cards */
  --text-muted:     #9a91ae;   /*  6.1:1 on cards */

  /* Borders */
  --border:         rgba(255, 255, 255, 0.08);
  --border-active:  rgba(232, 121, 249, 0.40);

  /* Tiers. The plain token is for dots, borders and fills (all above
     3:1 against the page, the WCAG floor for graphics). The -text token
     is for words set in that colour, above 8:1 on cards and on the
     tier's own tinted background. Never use colour alone: pair it with
     a word or a second signal (a strike through, Stop, Check). */
  --tier-red:          #f05252;
  --tier-red-text:     #fda4a4;
  --tier-red-bg:       rgba(240, 82, 82, 0.14);
  --tier-red-border:   rgba(240, 82, 82, 0.45);

  --tier-amber:        #f2a516;
  --tier-amber-text:   #fcd34d;
  --tier-amber-bg:     rgba(242, 165, 22, 0.14);
  --tier-amber-border: rgba(242, 165, 22, 0.45);

  --tier-green:        #2fbf71;
  --tier-green-text:   #86efac;
  --tier-green-bg:     rgba(47, 191, 113, 0.14);
  --tier-green-border: rgba(47, 191, 113, 0.45);

  /* Spacing scale */
  --sp-xs:  0.25rem;
  --sp-sm:  0.5rem;
  --sp-md:  1rem;
  --sp-lg:  1.5rem;
  --sp-xl:  2rem;
  --sp-2xl: 3rem;

  /* Typography */
  --font-sans: 'InterVariable', 'Inter', system-ui, sans-serif;
  --font-mono: ui-monospace, 'SFMono-Regular', Menlo, Consolas, monospace;

  /* Radii */
  --r-sm:   6px;
  --r-md:   12px;
  --r-lg:   20px;
  --r-full: 9999px;

  /* Shadows */
  --shadow-card: 0 8px 32px rgba(0, 0, 0, 0.55), 0 2px 8px rgba(0, 0, 0, 0.35);
  --shadow-glow: 0 0 40px rgba(232, 121, 249, 0.14);

  /* Transitions */
  --t-fast: 150ms ease;
  --t-med:  280ms cubic-bezier(0.4, 0, 0.2, 1);
  --t-slow: 420ms cubic-bezier(0.4, 0, 0.2, 1);

  /* Layout */
  --content-max: 960px;
  --gutter:      var(--sp-md);
}

/* ---- Reset and base ----------------------------------------------- */
*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

/* 100%, not 16px: the browser's own text-size setting must still apply (WCAG
   1.4.4); at the default setting it is the same 16px. */
html {
  font-size: 100%;
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  font-family: var(--font-sans);
  background-color: var(--bg-base);
  background-image:
    radial-gradient(ellipse at 12% -8%, rgba(232, 121, 249, 0.12) 0%, transparent 55%),
    radial-gradient(ellipse at 92% 108%, rgba(226, 30, 38, 0.07) 0%, transparent 50%);
  background-attachment: fixed;
  color: var(--text-primary);
  line-height: 1.6;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

h1, h2, h3, h4 {
  color: var(--text-primary);
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -0.02em;
}

img, svg, canvas { display: block; max-width: 100%; }

a { color: var(--accent-primary); text-underline-offset: 2px; }
a:hover { color: var(--text-primary); }

button, input, select, textarea { font: inherit; color: inherit; }

/* Visible keyboard focus (WCAG 2.4.7) */
:focus-visible {
  outline: 2px solid var(--accent-primary);
  outline-offset: 2px;
  border-radius: 4px;
}

/* Hidden on screen, still read aloud */
.visually-hidden {
  position: absolute !important;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* The hidden attribute must win over any display rule below */
[hidden] { display: none !important; }

/* ---- Main area and hero ------------------------------------------- */
.main-content {
  flex: 1;
  width: 100%;
  max-width: var(--content-max);
  margin: 0 auto;
  padding: var(--sp-xl) var(--gutter) var(--sp-2xl);
  display: flex;
  flex-direction: column;
  gap: var(--sp-xl);
}

.hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-md);
  text-align: center;
}

.hero-icon {
  width: 64px;
  height: 64px;
  filter: drop-shadow(0 0 14px rgba(232, 121, 249, 0.45));
}

.hero-title {
  font-size: clamp(1.9rem, 7vw, 3.2rem);
  font-weight: 700;
  line-height: 1.1;
  color: var(--text-primary);
  overflow-wrap: anywhere;
}

.hero-lede {
  max-width: 34rem;
  color: var(--text-secondary);
  font-size: 1.05rem;
  line-height: 1.55;
}

.noscript {
  padding: var(--sp-md);
  border: 1px solid var(--tier-amber-border);
  border-radius: var(--r-md);
  background: var(--tier-amber-bg);
  color: var(--tier-amber-text);
  text-align: center;
}

/* ---- Android app link (website only) ------------------------------ */
/* Marked data-web-only in the HTML: the Android app's bridge hides it,
   and the [hidden] rule above wins over the display rule here. */
.android-app {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-sm);
  text-align: center;
  color: var(--text-secondary);
  font-size: 0.9rem;
  line-height: 1.5;
}

.android-app p { max-width: 34rem; }

.android-app strong {
  color: var(--text-primary);
  font-weight: 600;
}

.android-app .btn {
  max-width: 100%;
  white-space: normal;
}

/* ---- Shared building blocks for the app UI ------------------------ */
.card {
  position: relative;
  width: 100%;
  padding: var(--sp-lg) var(--sp-md);
  background: var(--bg-card);
  -webkit-backdrop-filter: blur(16px);
  backdrop-filter: blur(16px);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-card);
}

/* Same top hairline the other Labs cards carry */
.card::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 1px;
  border-radius: var(--r-lg) var(--r-lg) 0 0;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.15), transparent);
  pointer-events: none;
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-sm);
  min-height: 44px;
  padding: 0.7rem 1.25rem;
  border: 1px solid transparent;
  border-radius: var(--r-md);
  font-family: var(--font-sans);
  font-size: 0.95rem;
  font-weight: 600;
  line-height: 1.2;
  text-decoration: none;
  cursor: pointer;
  transition: transform var(--t-fast), filter var(--t-fast), background var(--t-fast), border-color var(--t-fast);
}

.btn:hover { transform: translateY(-1px); }
.btn:active { transform: scale(0.98); }
.btn:disabled,
.btn[aria-disabled="true"] { opacity: 0.5; cursor: not-allowed; transform: none; }

.btn-primary {
  background: var(--grad-primary);
  color: var(--on-accent);
}
.btn-primary:hover { filter: brightness(1.08); color: var(--on-accent); }

.btn-secondary {
  background: rgba(255, 255, 255, 0.06);
  border-color: var(--border);
  color: var(--text-primary);
}
.btn-secondary:hover { background: rgba(255, 255, 255, 0.12); color: var(--text-primary); }

.btn-secondary[aria-pressed="true"] {
  background: var(--accent-soft);
  border-color: var(--border-active);
}

/* Tier marker. Use with data-tier="red|amber|green" and always with a
   word inside, so the tier never depends on colour alone. */
.tier-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  padding: 0.15em 0.6em;
  border: 1px solid var(--border);
  border-radius: var(--r-full);
  font-size: 0.78rem;
  font-weight: 600;
  line-height: 1.5;
  white-space: nowrap;
}

.tier-badge::before {
  content: '';
  width: 0.6em;
  height: 0.6em;
  border-radius: 50%;
  background: currentColor;
  flex-shrink: 0;
}

[data-tier="red"]   { --tier: var(--tier-red);   --tier-text: var(--tier-red-text);   --tier-bg: var(--tier-red-bg);   --tier-border: var(--tier-red-border); }
[data-tier="amber"] { --tier: var(--tier-amber); --tier-text: var(--tier-amber-text); --tier-bg: var(--tier-amber-bg); --tier-border: var(--tier-amber-border); }
[data-tier="green"] { --tier: var(--tier-green); --tier-text: var(--tier-green-text); --tier-bg: var(--tier-green-bg); --tier-border: var(--tier-green-border); }

.tier-badge[data-tier] {
  color: var(--tier-text);
  background: var(--tier-bg);
  border-color: var(--tier-border);
}

/* ---- App switcher carousel ---------------------------------------- */
/* Mechanics as in the other Labs apps: the track holds TEN identical
   sets of cards and slides by exactly one set (10%), so the loop is
   seamless. Change the number of sets and the -10% together. */
.app-switcher-container {
  padding: var(--sp-2xl) 0;
  margin-top: var(--sp-xl);
  text-align: center;
  border-top: 1px solid var(--border);
}

.switcher-title {
  margin-bottom: var(--sp-lg);
  padding: 0 var(--gutter);
  font-size: 1.2rem;
  font-weight: 600;
  letter-spacing: -0.5px;
  color: var(--text-secondary);
}

.app-switcher-marquee {
  display: flex;
  width: 100%;
  overflow: hidden;
  padding: 0.5rem var(--gutter) 1.5rem;
}

.app-switcher-track {
  display: flex;
  width: max-content;
  animation: marquee 32s linear infinite;
}

.app-switcher-marquee:hover .app-switcher-track,
.app-switcher-marquee:focus-within .app-switcher-track { animation-play-state: paused; }

@keyframes marquee {
  0%   { transform: translateX(0); }
  100% { transform: translateX(-10%); }
}

.switcher-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  flex-shrink: 0;
  margin-right: 1rem;
  padding: 1rem 1.5rem;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 12px;
  color: var(--text-primary);
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
  transition: transform 0.2s, background 0.2s, box-shadow 0.2s;
}

.switcher-card:hover {
  transform: translateY(-3px);
  background: var(--bg-card-hover);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.45);
  color: var(--text-primary);
}

/* Icon size here, not in an inline style="...", which this page's CSP
   would refuse. Every sibling app does the same since 2026-10-10. */
.switcher-card img {
  width: 32px;
  height: 32px;
  opacity: 0.9;
}

/* ---- Carousel and footer access (2026-10-10) ---------------------- */
/* The page's own app, the last card of every set, is marked for screen
   readers (aria-current) and for the eye (an accent border). */
.switcher-card[aria-current="page"] { border-color: var(--accent-primary); }

/* Rounded focus ring, whatever corner radius the page's own ring uses */
.switcher-card:focus-visible { border-radius: 12px; }

/* Keyboard focus stops the slide and the row scrolls to the focused card,
   so it is never off-screen. :focus-visible and not :focus-within, so a
   mouse click does not move the card from under the pointer. */
.app-switcher-marquee:has(.switcher-card:focus-visible) { overflow-x: auto; }
.app-switcher-marquee:has(.switcher-card:focus-visible) .app-switcher-track { animation: none; }

/* The pause tick box (WCAG 2.2.2): ticked, the slide stops and the row
   scrolls by hand. Plain CSS, no script. `all: revert` keeps the page's
   own form styles off it. */
.app-switcher-container input.switcher-pause {
  all: revert;
  margin: 0 0.5rem 0.75rem 0;
  vertical-align: middle;
  accent-color: var(--accent-primary);
  cursor: pointer;
}

.app-switcher-container label.switcher-pause-label {
  all: revert;
  display: inline-block;
  margin-bottom: 0.75rem;
  vertical-align: middle;
  color: var(--text-secondary);
  font-size: 0.85rem;
  cursor: pointer;
}

.app-switcher-container input.switcher-pause:focus-visible {
  outline: 2px solid var(--accent-primary);
  outline-offset: 2px;
}

.switcher-pause:checked ~ .app-switcher-marquee { overflow-x: auto; }
.switcher-pause:checked ~ .app-switcher-marquee .app-switcher-track { animation: none; }

/* A footer link never breaks inside itself (the org.nr. did at 320 px) */
.footer-bottom p a { white-space: nowrap; }

@media (prefers-reduced-motion: reduce) {
  /* Nothing slides, so there is nothing to pause. */
  .app-switcher-container input.switcher-pause,
  .app-switcher-container label.switcher-pause-label { display: none; }
}

/* ---- Footer -------------------------------------------------------- */
.site-footer {
  margin-top: auto;
  padding: 4rem 1.5rem 2rem;
  background: var(--bg-base);
  border-top: 1px solid var(--border);
}

.footer-inner {
  max-width: 680px;
  margin: 0 auto 3rem;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: flex-start;
  gap: 2rem;
}

.footer-brand { max-width: 320px; }

.footer-logo {
  display: inline-block;
  margin-bottom: 0.5rem;
  font-family: var(--font-sans);
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--text-primary);
  text-decoration: none;
}

.footer-logo:hover { color: var(--text-primary); }
.footer-dot { color: var(--accent-primary); }

.footer-tagline {
  color: var(--text-secondary);
  font-size: 0.95rem;
  line-height: 1.5;
}

.footer-powered p {
  max-width: 250px;
  color: var(--text-secondary);
  font-size: 0.88rem;
  line-height: 1.6;
}

.footer-bottom {
  max-width: 680px;
  margin: 0 auto;
  padding-top: 2rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
  border-top: 1px solid rgba(255, 255, 255, 0.05);
  text-align: center;
}

.footer-social { display: flex; flex-wrap: wrap; justify-content: center; gap: 1.25rem; }
.footer-social a { color: var(--text-muted); transition: color var(--t-fast), transform var(--t-fast); }
.footer-social a:hover { color: var(--text-primary); transform: translateY(-2px); }
.footer-social svg { display: block; }

.footer-bottom p { color: var(--text-muted); font-size: 0.85rem; }

/* Footer legibility, as fixed across the estate on 2026-09-05: links take
   the app's own accent (8.0:1 here) instead of the browser default blue,
   and keep their underline, because colour alone must not be the only
   thing marking a link. */
.footer-bottom p a {
  color: var(--accent-primary);
  text-decoration: underline;
  text-underline-offset: 2px;
  transition: color var(--t-fast);
}

.footer-bottom p a:hover { color: var(--text-primary); }

/* The public test of the privacy claim */
.footer-bottom .footer-offline {
  color: var(--text-secondary);
  font-size: 0.9rem;
  font-weight: 600;
}

/* Kept readable: 5.0:1 at this opacity */
.footer-privacy, .footer-ai { opacity: 0.85; }

/* ---- Wider screens ------------------------------------------------- */
@media (min-width: 720px) {
  :root { --gutter: var(--sp-xl); }

  .main-content { padding-top: var(--sp-2xl); }

  .card { padding: var(--sp-xl); }

  .footer-powered p { text-align: right; }
}

/* ---- Reduced motion ------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  /* No sliding: the carousel becomes a row the reader scrolls. */
  .app-switcher-track { animation: none; }
  .app-switcher-marquee { overflow-x: auto; }

  .btn,
  .switcher-card,
  .footer-social a { transition: none; }

  .btn:hover,
  .btn:active,
  .switcher-card:hover,
  .footer-social a:hover { transform: none; }
}

/* ================================================================
   APP INTERFACE
   Everything below styles CheckLink itself, inside <main>. It uses
   the tokens above and leaves the footer and carousel alone.
   Prefix: cl-. Removed parts take the red tier tokens AND a strike
   through, so colour is never the only signal (WCAG 2.2 SC 1.4.1);
   the host a link goes to is bold and underlined, not a third colour.
================================================================ */

/* ---- Cards and text ------------------------------------------------ */
.cl-card {
  display: flex;
  flex-direction: column;
  gap: var(--sp-md);
}

.cl-card-title {
  font-size: 1.25rem;
  font-weight: 650;
}

.cl-help {
  color: var(--text-secondary);
  font-size: 0.92rem;
  line-height: 1.5;
}

.cl-label {
  font-weight: 600;
  font-size: 0.95rem;
  color: var(--text-primary);
}

.cl-btn-small {
  min-height: 40px;
  padding: 0.45rem 0.9rem;
  font-size: 0.88rem;
}

.cl-field {
  display: grid;
  gap: 0.4rem;
  min-width: 0;
}

/* Addresses are set in Inter with its disambiguation set (ss02), so l, I
   and 1, and 0 and O, look different. Long links wrap anywhere and are
   never cut short. */
.cl-addr {
  font-family: var(--font-sans);
  font-feature-settings: "ss02" 1;
  overflow-wrap: anywhere;
}

/* ---- The input ------------------------------------------------------ */
.cl-input {
  width: 100%;
  min-height: 5.5rem;
  padding: 0.6rem 0.75rem;
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: var(--r-md);
  background: var(--bg-surface);
  color: var(--text-primary);
  font-size: 1rem;
  line-height: 1.5;
  resize: vertical;
}

.cl-input:hover { border-color: rgba(255, 255, 255, 0.32); }

.cl-input:focus-visible {
  outline: 2px solid var(--accent-primary);
  outline-offset: 1px;
  border-color: var(--accent-primary);
}


/* ---- Result layout -------------------------------------------------- */
/* One column on every screen, in the order of the spec: what was found,
   the full link, the parts, the warnings, then the clean link. Reading
   order, tab order and visual order are the same. */
.cl-result {
  display: grid;
  gap: var(--sp-lg);
  grid-template-columns: minmax(0, 1fr);
}

/* ---- Summary --------------------------------------------------------- */
.cl-summary {
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--text-primary);
}

.cl-goes {
  color: var(--text-secondary);
  font-size: 1rem;
  overflow-wrap: anywhere;
}

.cl-goes .cl-host { color: var(--text-primary); }

/* ---- Notices and notes ----------------------------------------------- */
.cl-notice {
  padding: 0.75rem 1rem;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: rgba(255, 255, 255, 0.04);
  color: var(--text-secondary);
  font-size: 0.93rem;
  line-height: 1.5;
  overflow-wrap: anywhere;
}

.cl-notice[data-tier] {
  border-color: var(--tier-border);
  background: var(--tier-bg);
  color: var(--tier-text);
}

.cl-notes {
  display: grid;
  gap: var(--sp-sm);
  list-style: none;
}

.cl-note {
  position: relative;
  padding: 0.55rem 0.8rem 0.55rem 1.6rem;
  border-radius: var(--r-sm);
  background: rgba(255, 255, 255, 0.04);
  color: var(--text-secondary);
  font-size: 0.9rem;
  line-height: 1.45;
  overflow-wrap: anywhere;
}

.cl-note::before {
  content: '';
  position: absolute;
  left: 0.7rem;
  top: 1.05em;
  width: 0.4rem;
  height: 0.4rem;
  border-radius: 50%;
  background: var(--accent-primary);
}

.cl-note[data-tier] {
  background: var(--tier-bg);
  color: var(--tier-text);
}

.cl-note[data-tier]::before { background: var(--tier); }

/* The tier's word (Stop, Check, Good to know) before each note, so the
   tier never depends on colour alone. */
.cl-note-tier { font-weight: 700; }

/* ---- The full link ---------------------------------------------------- */
.cl-link {
  padding: 0.75rem 0.9rem;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: rgba(255, 255, 255, 0.03);
  color: var(--text-primary);
  font-size: 1rem;
  line-height: 1.75;
}

.cl-removed {
  color: var(--tier-red-text);
  background: var(--tier-red-bg);
  text-decoration-line: line-through;
  text-decoration-color: var(--tier-red);
  text-decoration-thickness: 2px;
  border-radius: 3px;
}

.cl-host {
  font-weight: 700;
  text-decoration-line: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
}

/* A part CheckLink found but keeps, because its box is unticked: an amber
   dotted underline inside a dashed amber box on an amber fill, explained in the
   legend. The box is a shape, not only a colour, so it still reads apart from
   the kept-on-purpose underline below in greyscale (WCAG 1.4.1). Each line of a
   wrapped part gets its own box. */
.cl-kept-part {
  text-decoration-line: underline;
  text-decoration-style: dotted;
  text-decoration-color: var(--tier-amber);
  text-decoration-thickness: 2px;
  text-underline-offset: 4px;
  background: rgba(242, 165, 22, 0.16);
  outline: 1.5px dashed var(--tier-amber);
  outline-offset: 1px;
  border-radius: 3px;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}

/* A parameter kept on purpose (a start time, the size chosen): a grey dotted
   underline with no fill and no box, the legend's third style, so it reads apart
   from both the red removed parts and the boxed unticked ones. */
.cl-func-part {
  text-decoration-line: underline;
  text-decoration-style: dotted;
  text-decoration-color: var(--text-muted);
  text-decoration-thickness: 2px;
  text-underline-offset: 4px;
}

/* A letter from another alphabet that only looks like a Latin one, in an address that a
   look-alike note names (interface review M1 of stage 3): a box round the letter itself, drawn by
   the style sheet alone, so the address still copies as written. The legend shows one. */
.cl-foreign {
  padding: 0 0.08em;
  border: 1px solid var(--tier-amber-border);
  border-radius: 3px;
  background: var(--tier-amber-bg);
  color: var(--tier-amber-text);
  text-decoration: inherit;
}

/* A short xn-- name in a note, kept on one line: broken after its double hyphen it reads like a
   dash. */
.cl-nowrap { white-space: nowrap; }

/* An invisible or direction-changing character, drawn as a visible mark
   (U+202E and so on) so it cannot reorder or hide the address around it.
   The text copied is the link itself, not the mark. */
.cl-invis {
  display: inline-block;
  margin: 0 0.1em;
  padding: 0 0.3em;
  border: 1px solid var(--tier-amber-border);
  border-radius: 3px;
  background: var(--tier-amber-bg);
  color: var(--tier-amber-text);
  font-size: 0.72em;
  font-weight: 700;
  line-height: 1.4;
  vertical-align: 0.1em;
  text-decoration: none;
  white-space: nowrap;
}

.cl-target {
  display: grid;
  gap: var(--sp-xs);
}

.cl-sub {
  color: var(--text-secondary);
  font-size: 0.92rem;
  font-weight: 600;
}

.cl-legend {
  display: grid;
  gap: 0.2rem;
  list-style: none;
  color: var(--text-secondary);
  font-size: 0.88rem;
  line-height: 1.5;
}

.cl-legend .cl-host { color: var(--text-primary); }

/* ---- The parts --------------------------------------------------------- */
.cl-count {
  color: var(--text-secondary);
  font-size: 0.9rem;
}

.cl-parts {
  display: grid;
  gap: var(--sp-sm);
  list-style: none;
  min-width: 0;
}

/* A link can carry thousands of parts (the box takes 20,000 characters).
   Rows off screen skip layout and painting until they scroll into view;
   they stay in the page, so find-in-page and screen readers still reach
   them. Browsers without content-visibility simply draw every row. */
.cl-part-li {
  min-width: 0;
  content-visibility: auto;
  contain-intrinsic-size: auto 6rem;
}

/* The whole row is the tick box's label, as in MetadataScrubber. */
.cl-part {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  min-width: 0;
  padding: 0.65rem 0.8rem;
  border: 1px solid var(--border);
  border-left: 4px solid var(--text-muted);
  border-radius: var(--r-md);
  background: rgba(255, 255, 255, 0.025);
  cursor: pointer;
  transition: background var(--t-fast), border-color var(--t-fast);
}

.cl-part:hover { background: rgba(255, 255, 255, 0.06); }

.cl-part.is-ticked {
  background: var(--tier-red-bg);
  border-color: var(--tier-red-border);
  border-left-color: var(--tier-red);
}

.cl-part.is-disabled { cursor: not-allowed; }
.cl-part.is-disabled .cl-part-body { opacity: 0.75; }

.cl-part:has(.cl-check:focus-visible) {
  outline: 2px solid var(--accent-primary);
  outline-offset: 2px;
}

.cl-check {
  flex-shrink: 0;
  width: 1.2rem;
  height: 1.2rem;
  margin: 0.2rem 0 0;
  accent-color: var(--accent-primary);
  cursor: pointer;
}

.cl-check:disabled { cursor: not-allowed; }

.cl-part-body {
  display: grid;
  /* One column that never grows past the row, so a long badge or name
     wraps instead of pushing the row wider than the screen. */
  grid-template-columns: minmax(0, 1fr);
  gap: 0.2rem;
  min-width: 0;
  flex: 1;
}

/* Name on the left, the badge on the right; the badge wraps under the
   name when the line is short. */
.cl-part-top {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.2rem 0.6rem;
  min-width: 0;
}

.cl-part-name {
  font-weight: 650;
  line-height: 1.35;
  overflow-wrap: anywhere;
  min-width: 0;
}

.cl-part-value {
  color: var(--text-secondary);
  font-size: 0.9rem;
  line-height: 1.4;
}

.cl-part-provider {
  color: var(--text-primary);
  font-size: 0.9rem;
  font-weight: 600;
  line-height: 1.4;
}

.cl-part-who {
  color: var(--text-primary);
  font-size: 0.9rem;
  line-height: 1.45;
}

.cl-part-told {
  color: var(--text-secondary);
  font-size: 0.9rem;
  line-height: 1.45;
}

.cl-part-aff {
  color: var(--tier-amber-text);
  font-size: 0.88rem;
  font-weight: 600;
  line-height: 1.4;
}

.cl-part-note {
  color: var(--text-muted);
  font-size: 0.84rem;
  line-height: 1.4;
}

/* "Same kind as the part above.": stands in for a label and explanation the row
   above has just given. */
.cl-part-same {
  color: var(--text-muted);
  font-size: 0.9rem;
  line-height: 1.45;
}

/* "Unique to this click" or "Same for everyone who got this link": a word,
   never a colour alone. */
.cl-badge {
  display: inline-flex;
  align-items: center;
  padding: 0.1em 0.6em;
  border: 1px solid var(--border);
  /* Not a full pill: a badge that wraps onto two lines with large text would
     clip its words in an oval. */
  border-radius: 0.85em;
  color: var(--text-secondary);
  font-size: 0.78rem;
  font-weight: 600;
  line-height: 1.5;
  /* Wraps on narrow screens and with large text instead of spilling out of
     its row (WCAG 1.4.10 and 1.4.4). */
  white-space: normal;
  max-width: 100%;
}

.cl-badge[data-kind="unique"] {
  color: var(--tier-amber-text);
  background: var(--tier-amber-bg);
  border-color: var(--tier-amber-border);
}

/* The address disguise says what it is (Misleading, or Readable by anyone for
   sign-in details); a sharer ID follows the account that shared the link. Both
   point at a person or a trick, so amber. */
.cl-badge[data-kind="check"],
.cl-badge[data-kind="sharer"] {
  color: var(--tier-amber-text);
  background: var(--tier-amber-bg);
  border-color: var(--tier-amber-border);
}

/* "Unrecognised": a part on none of the verified lists, on a page fully
   addressed by its path. A neutral word with a dashed outline straight after
   the name, and a dashed left edge on its row, so it reads apart from the
   verified trackers; the row still turns red and the part is still struck
   through when ticked. The word wraps under the name on a narrow line. */
.cl-part-head {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.2rem 0.5rem;
  min-width: 0;
  max-width: 100%;
}

.cl-tag {
  display: inline-flex;
  align-items: center;
  padding: 0.1em 0.6em;
  border: 1px dashed var(--text-muted);
  border-radius: 0.85em;
  color: var(--text-secondary);
  font-size: 0.78rem;
  font-weight: 600;
  line-height: 1.5;
  white-space: normal;
  max-width: 100%;
}

.cl-part[data-unrecognised] { border-left-style: dashed; }

/* ---- Kept on purpose --------------------------------------------------- */
/* Rows like the parts above, with a dotted grey left edge to match the grey
   dotted underline in the full link. Ticked ("Remove anyway"), a row turns red
   like any part. */
.cl-kept {
  display: grid;
  gap: var(--sp-sm);
  min-width: 0;
  padding-top: var(--sp-md);
  border-top: 1px solid var(--border);
}

.cl-kept-row { border-left-style: dotted; }

/* "Remove anyway" straight after the name, next to the box it labels, rather
   than at the far end of the row. */
.cl-kept-row .cl-part-top { justify-content: flex-start; }

/* "Remove anyway", where a part has its badge: the words for the box. */
.cl-anyway {
  color: var(--text-secondary);
  font-size: 0.8rem;
  font-weight: 600;
  line-height: 1.5;
  white-space: normal;
  max-width: 100%;
}

.cl-kept-row.is-ticked .cl-anyway { color: var(--tier-red-text); }

/* ---- Hidden addresses, offers and other links -------------------------- */
.cl-extra {
  display: grid;
  gap: var(--sp-sm);
  min-width: 0;
}

.cl-extra-title {
  font-size: 1rem;
  font-weight: 650;
}

/* One column that never grows past the card, so a long word in the help line
   (a host with no hyphens) wraps instead of making the page scroll sideways. */
.cl-extra-list {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--sp-sm);
  list-style: none;
  min-width: 0;
}

.cl-extra-item {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--sp-xs);
  justify-items: start;
  min-width: 0;
}

.cl-extra-item .cl-help { overflow-wrap: anywhere; }

.cl-extra-item .cl-link { justify-self: stretch; }

/* ---- The clean link and its actions ------------------------------------ */
.cl-clean {
  padding: 0.8rem 1rem;
  border: 1px solid var(--border-active);
  border-radius: var(--r-md);
  background: var(--accent-soft);
  color: var(--text-primary);
  font-size: 1.02rem;
  line-height: 1.6;
  -webkit-user-select: all;
  user-select: all;
}

.cl-actions {
  display: grid;
  gap: var(--sp-sm);
}

.cl-action-btn,
.cl-go {
  width: 100%;
  overflow-wrap: anywhere;
  line-height: 1.35;
}

/* "Did CheckLink break your link? Email us": a small line under Go to. */
.cl-report {
  font-size: 0.86rem;
  color: var(--text-muted);
  overflow-wrap: anywhere;
}

.cl-report-link {
  color: var(--accent-primary);
  text-decoration-line: underline;
  text-underline-offset: 2px;
  white-space: nowrap;
}

.cl-report-link:hover { color: var(--text-primary); }

.cl-report-link:focus-visible {
  outline: 2px solid var(--accent-primary);
  outline-offset: 2px;
  border-radius: 2px;
}

/* Stays rendered when empty, so screen readers hear what is written into it later. */
.cl-status {
  color: var(--text-secondary);
  font-size: 0.92rem;
}

.cl-status:empty { margin-top: calc(-1 * var(--sp-md)); }

/* ---- A QR code of the clean link (stage 4b) ----------------------------- */
/* Always black on white with its quiet zone, whatever the page's colours: many scanners cannot read
   a light code on a dark ground. The code is one SVG path whose colours are presentation
   attributes (fill), which the page policy allows; the frame only sizes it, and keeps Windows'
   high-contrast colours off it (forced-color-adjust). At most 18rem wide, never wider than the
   card. */
.cl-qr-frame {
  width: min(100%, 18rem);
  margin-inline: auto;
  border-radius: var(--r-sm);
  background: #ffffff;
  line-height: 0;
  forced-color-adjust: none;
}

.cl-qr-svg {
  display: block;
  width: 100%;
  height: auto;
}

/* The exact text the code holds, as plain text in a box: never a live link. */
.cl-qr-text {
  padding: 0.6rem 0.8rem;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: rgba(255, 255, 255, 0.04);
  color: var(--text-primary);
  font-size: 0.95rem;
  line-height: 1.5;
}

/* ---- The Go to confirmation -------------------------------------------- */
.cl-dialog {
  width: min(34rem, calc(100vw - 2 * var(--sp-md)));
  max-width: none;
  margin: auto;
  padding: var(--sp-lg);
  border: 1px solid var(--border-active);
  border-radius: var(--r-lg);
  background: var(--bg-card-solid);
  color: var(--text-primary);
  box-shadow: var(--shadow-card);
}

.cl-dialog[open] {
  display: grid;
  gap: var(--sp-md);
}

.cl-dialog::backdrop { background: rgba(8, 6, 12, 0.72); }

.cl-dialog-title {
  font-size: 1.2rem;
  font-weight: 650;
  overflow-wrap: anywhere;
}

.cl-dialog-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: var(--sp-sm);
}

.cl-dialog-actions .btn {
  flex: 1 1 auto;
  max-width: 100%;
  overflow-wrap: anywhere;
}

/* ---- Pictures (stage 2) ------------------------------------------------- */
/* Choose a picture of a QR code sits under the box with Clear at the end of the same row, and
   its help line under both. Both buttons are at least 44 pixels tall (WCAG 2.5.5). Dropping a
   picture anywhere outlines the input card. */
.cl-pic-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-sm) var(--sp-md);
  min-width: 0;
}

.cl-pic-row .btn {
  min-height: 44px;
  max-width: 100%;
  overflow-wrap: anywhere;
}

.cl-pic-btn { font-weight: 650; }

/* On a narrow screen the two buttons share the row's width evenly when they fit side by side, and
   each takes the whole row when they do not, rather than leaving a ragged gap. */
@media (max-width: 480px) {
  .cl-pic-row .cl-pic-btn,
  .cl-pic-row .cl-cam-btn { flex: 1 1 12rem; }
}

.cl-clear-btn { margin-left: auto; }

/* Android app only (stage 4): the button to Android's settings after a camera refusal, at the end
   of the input card, at its own width and 44 pixels tall like the buttons above. */
.cl-settings-btn {
  align-self: flex-start;
  min-height: 44px;
  max-width: 100%;
  overflow-wrap: anywhere;
}

/* A picture that cannot be read says so in full-strength text in a box, not as help text. */
.cl-status.is-error {
  padding: 0.6rem 0.8rem;
  border: 1px solid var(--tier-amber-border);
  border-radius: var(--r-md);
  background: var(--tier-amber-bg);
  color: var(--text-primary);
}

#input-card.is-dropping {
  outline: 2px dashed var(--accent-primary);
  outline-offset: 4px;
}

.cl-picture {
  display: block;
  max-width: 100%;
  height: auto;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--bg-surface);
}

.cl-picture[hidden] { display: none; }

/* ---- The live camera (stage 3) ------------------------------------------ */
/* Scan with camera sits between the picture button and Clear. The camera card shows the
   preview at the card's width, never taller than half the screen, so Stop camera stays in view
   on a phone. The video is a picture of the camera, not a control: it takes no pointer and has
   no controls. */
.cl-cam-btn { font-weight: 650; }

/* The frame takes the shape of what the camera sends (--cam-w and --cam-h, set by the page once
   the camera has said its size; 4:3 until then), so the preview shows the whole frame the decoder
   reads, never a crop of it (interface review L4 of stage 3). A tall frame from a phone held
   upright narrows rather than growing past half the screen. */
.cl-cam-frame {
  position: relative;
  width: 100%;
  width: min(100%, 36rem, calc(50vh * var(--cam-w, 4) / var(--cam-h, 3)));
  width: min(100%, 36rem, calc(50svh * var(--cam-w, 4) / var(--cam-h, 3)));
  max-width: 36rem;
  margin-inline: auto;
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--bg-surface);
  aspect-ratio: 4 / 3;
  aspect-ratio: var(--cam-w, 4) / var(--cam-h, 3);
  max-height: 50vh;
  max-height: 50svh;
  min-width: 0;
}

.cl-cam-video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  pointer-events: none;
}

/* A square in the middle shows where to hold the code; drawn with borders only, so it never
   hides the preview. */
.cl-cam-frame::after {
  content: "";
  position: absolute;
  inset: 18% 24%;
  border: 2px dashed var(--accent-primary);
  border-radius: var(--r-md);
  pointer-events: none;
}

#camera-card .cl-status:not(:empty) { font-weight: 600; color: var(--text-primary); }

/* One entry per code. The left edge carries the tier colour; the tier's word is always written
   too (Stop, Check, Good to know), so colour is never the only signal. */
.cl-codes {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--sp-md);
  list-style: none;
  min-width: 0;
}

.cl-code {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--sp-sm);
  min-width: 0;
  padding: var(--sp-md);
  border: 1px solid var(--border);
  border-left: 4px solid var(--accent-primary);
  border-radius: var(--r-md);
  background: rgba(255, 255, 255, 0.03);
}

.cl-code[data-tier] { border-left-color: var(--tier); }

/* Good to know codes keep a neutral grey edge: the accent sits too close to the Stop red. */
.cl-code:not([data-tier]) { border-left-color: var(--text-muted); }

/* A Stop code stands out as a whole, not only by its edge. */
.cl-code[data-tier="red"] {
  background: var(--tier-bg);
  border-color: var(--tier-border);
  border-left-color: var(--tier);
}

.cl-code-title {
  font-size: 1.02rem;
  font-weight: 650;
  overflow-wrap: anywhere;
}

.cl-code-format {
  margin-top: calc(-1 * var(--sp-xs));
  color: var(--text-muted);
  font-size: 0.86rem;
}

/* Beside other codes, the owner of each address (Goes to ...). */
.cl-code-goes { font-size: 0.92rem; }


.cl-code-summary {
  color: var(--text-secondary);
  font-size: 0.95rem;
  line-height: 1.5;
}

.cl-code[data-tier] .cl-code-summary .cl-note-tier { color: var(--tier-text); }

/* The details of a code: label above value on narrow screens, side by side on wide ones. */
.cl-fields {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--sp-sm);
  min-width: 0;
}

.cl-field-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0.15rem;
  min-width: 0;
  padding-bottom: var(--sp-sm);
  border-bottom: 1px solid var(--border);
}

.cl-field-row:last-child { border-bottom: 0; padding-bottom: 0; }

.cl-field-label {
  color: var(--text-muted);
  font-size: 0.86rem;
}

.cl-field-dd {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--sp-xs);
  justify-items: start;
  min-width: 0;
  margin: 0;
}

.cl-field-value {
  color: var(--text-primary);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  max-width: 100%;
}

.cl-mono { letter-spacing: 0.01em; }

.cl-secret[data-shown="false"] { color: var(--text-muted); }

.cl-field-note {
  color: var(--text-muted);
  font-size: 0.85rem;
  line-height: 1.4;
}

.cl-field-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-xs) var(--sp-sm);
  max-width: 100%;
}

.cl-field-actions .btn {
  max-width: 100%;
  overflow-wrap: anywhere;
}

.cl-code-links .cl-btn-small { max-width: 100%; }

.cl-code-text summary {
  cursor: pointer;
  color: var(--text-secondary);
  font-size: 0.9rem;
}

.cl-code-text summary:focus-visible {
  outline: 2px solid var(--accent-primary);
  outline-offset: 2px;
  border-radius: 2px;
}

.cl-code-text p {
  margin-top: var(--sp-xs);
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: rgba(255, 255, 255, 0.03);
  color: var(--text-primary);
  font-size: 0.92rem;
  white-space: pre-wrap;
}

.cl-code-text p.cl-help {
  border: 0;
  background: none;
  padding: 0;
  color: var(--text-secondary);
}

.cl-code .cl-status:empty { display: none; }

/* Narrow screens: paddings in rem double with the text size, which left the notes of a code a
   few letters wide at 200% text on a 320-pixel screen. Here they are capped in pixels. */
@media (max-width: 480px) {
  :root { --gutter: min(var(--sp-md), 16px); }

  #picture-card,
  #camera-card { padding-inline: 12px; }

  .cl-code { padding: 8px 10px; }

  .cl-code .cl-note { padding-inline: 1.1em 8px; }

  .cl-code .cl-note::before { left: 0.35em; width: 0.4em; height: 0.4em; }

  .cl-code .cl-link { padding: 6px 8px; }
}

/* ---- Wider screens ----------------------------------------------------- */
@media (min-width: 720px) {
  .cl-actions {
    display: flex;
    flex-wrap: wrap;
  }

  .cl-field-row {
    grid-template-columns: minmax(8rem, 12rem) minmax(0, 1fr);
    gap: var(--sp-md);
  }

  .cl-action-btn,
  .cl-go {
    width: auto;
    max-width: 100%;
  }

  .cl-go { align-self: flex-start; }

  .cl-dialog-actions .btn { flex: 0 1 auto; }
}

/* ---- Reduced motion ---------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .cl-part { transition: none; }
}

@media (forced-colors: active) {
  .cl-cam-frame::after { border-color: CanvasText; }
}

/* ================================================================
   PRIVACY PAGE (privacy.html)
   The same chrome as the app: hero, one card, the site footer. The
   page has the app's own policy (style-src 'self'), so its few rules
   live here. Prefix: pp-.
================================================================ */
.pp-back {
  align-self: flex-start;
  color: var(--text-secondary);
  font-size: 0.9rem;
  text-decoration: none;
}

.pp-back:hover { color: var(--accent-primary); }

.pp-doc {
  max-width: 46rem;
  margin: 0 auto;
}

.pp-doc h2 {
  font-size: 1.15rem;
  font-weight: 650;
  margin: var(--sp-xl) 0 var(--sp-sm);
}

.pp-doc h2:first-child { margin-top: 0; }

.pp-doc p {
  color: var(--text-secondary);
  line-height: 1.65;
  overflow-wrap: anywhere;
}

.pp-doc p + p { margin-top: var(--sp-md); }

.pp-doc strong {
  color: var(--text-primary);
  font-weight: 600;
}

.pp-doc .pp-updated {
  margin-top: var(--sp-xl);
  padding-top: var(--sp-md);
  border-top: 1px solid var(--border);
  color: var(--text-muted);
  font-size: 0.88rem;
}

/* ================================================================
   FIRST-RUN NOTICE (gate.css, generated by build-gates.py)
   gate.css is written by the shared generator for every gated Labs
   app and is not edited here. It holds the dialog to 88% of the
   screen's height and clips the rest, which at 200% text on a 320 by
   640 screen hid Got it below the screen with no way to reach it. In
   CheckLink the notice itself scrolls instead: the prose keeps its own
   scroll area, the dialog is never clipped, and when it is taller than
   the screen the overlay scrolls from its top ("safe" keeps the top
   reachable). The selectors are one step more specific than
   gate.css's, which loads after this file.
================================================================ */
html .sb-gate-overlay {
  overflow-y: auto;
  align-items: safe center;
}

.sb-gate-overlay .sb-gate-dialog {
  max-height: none;
  overflow: visible;
}

/* The prose keeps gate.css's own scroll area: what is left of 88% of the screen's height once
   the heading, the last line and the buttons (about 20rem) have their room, and never less than
   12rem, so at very large text it stays readable and the notice scrolls as a whole. */
.sb-gate-overlay .sb-gate-scroll {
  max-height: max(12rem, calc(88vh - 20rem));
}
