/* ===========================================================================
   QR CODE GENERATOR — the tool's own interface.

   Same rules as image-compressor-styling.css next door: every colour is a
   site token or derived from one, so the panel follows the reader's theme.
   The one fixed palette is the transparency checkerboard behind the preview,
   same reasoning as ic's and br's.

   The QR code itself is NOT themed. It's drawn in whatever colours the
   reader picked, because that's the thing they're downloading, and a code
   that quietly went light-on-dark when the site did would be a preview of
   something they aren't getting.

   Unlike .ic-app, the app box here has no overflow: hidden. The preview
   column is position: sticky so it stays on screen while the settings
   column scrolls past, and any overflow other than visible on an ancestor
   turns that ancestor into the sticky element's scroll container, which
   never scrolls, so the preview would just sit still. The rounded corners
   are handed to the toolbar and status bar instead.

   Two pieces live outside .qr-app on purpose: the colour picker popover and
   the phone-sized mini preview are appended to <body> by qr-generator.js.
   Both are position: fixed, and the scroll-reveal system puts a transform on
   .qr-app while it animates in, which would otherwise turn "fixed" into
   "fixed to the tool". They're styled from the site tokens directly below.
   =========================================================================== */

.qr-app {
    --qr-surface: var(--color-primary-a10);
    --qr-surface-raised: var(--color-primary-a20);
    --qr-border: var(--color-card-border);
    --qr-border-strong: var(--color-primary-a20);

    --qr-checker-a: #4a4a4a;
    --qr-checker-b: #5c5c5c;

    --qr-mono: "JetBrains Mono", "Fira Mono", "Consolas", ui-monospace, monospace;
    --qr-sans: "Circular Spotify", "Inter", sans-serif;

    font-family: var(--qr-sans);
    color: var(--color-text-1);

    display: flex;
    flex-direction: column;
    background: var(--qr-surface);
    border: 1px solid var(--qr-border);
    border-radius: 16px;
}

.qr-app :is(button, input, select, textarea, summary, a):focus-visible {
    outline: 2px solid var(--color-selected-3);
    outline-offset: 2px;
}

/* ---------------------------------------------------------------------------
   Toolbar and status bar
   --------------------------------------------------------------------------- */

.qr-toolbar {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    padding: 10px 12px;
    background: var(--qr-surface-raised);
    border-bottom: 1px solid var(--qr-border);
    border-radius: 15px 15px 0 0;
}

.qr-toolbar-spacer { margin-left: auto; }
.qr-toolbar-group { display: flex; gap: 4px; }

.qr-summary {
    font-family: var(--qr-mono);
    font-size: 12px;
    color: var(--color-text-2);
}

.qr-icon-btn {
    width: 32px;
    height: 32px;
    display: grid;
    place-items: center;
    border-radius: 8px;
    border: 1px solid var(--qr-border-strong);
    background: transparent;
    color: var(--color-text-2);
    cursor: pointer;
    transition:
        background-color var(--dur-hover) var(--ease-soft),
        color var(--dur-hover) var(--ease-soft),
        transform var(--dur-hover) var(--ease-pop);
}

.qr-icon-btn svg {
    width: 17px;
    height: 17px;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
}

@media (hover: hover) {
    .qr-icon-btn:hover:not(:disabled) { background: var(--color-primary-a20); color: var(--color-text-1); }
}

.qr-icon-btn:active:not(:disabled) { transform: scale(0.94); transition-duration: var(--dur-press); }
.qr-icon-btn:disabled { opacity: 0.35; cursor: default; }

.qr-statusbar {
    padding: 9px 12px;
    border-top: 1px solid var(--qr-border);
    background: var(--qr-surface-raised);
    border-radius: 0 0 15px 15px;
    font-size: 12px;
    color: var(--color-text-2);
    min-height: 1.5em;
}

.qr-status {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 5px 11px;
    border-radius: 24px;
    font-size: 11.5px;
    font-weight: 600;
}

.qr-status:empty { display: none; }

.qr-status[data-tone="ok"] { background: rgba(74, 222, 128, 0.14); color: #38b869; }
:root:not([data-theme="light"]) .qr-status[data-tone="ok"] { color: #4ade80; }

.qr-status[data-tone="error"] { background: rgba(231, 140, 140, 0.16); color: var(--color-warning-2); }
:root:not([data-theme="light"]) .qr-status[data-tone="error"] { color: var(--color-warning-1); }

.qr-status[data-tone="info"] { background: rgba(91, 148, 198, 0.16); color: var(--color-accent-text); }

/* ---------------------------------------------------------------------------
   Buttons — identical contract to .ic-btn.
   --------------------------------------------------------------------------- */

.qr-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    min-height: 32px;
    padding: 6px 14px;
    border-radius: 8px;
    border: 1px solid var(--qr-border-strong);
    background: transparent;
    color: var(--color-text-2);
    font-family: var(--qr-sans);
    font-size: 12px;
    font-weight: 600;
    line-height: 1.2;
    white-space: nowrap;
    cursor: pointer;
    transition:
        background-color var(--dur-hover) var(--ease-soft),
        border-color var(--dur-hover) var(--ease-soft),
        color var(--dur-hover) var(--ease-soft),
        transform var(--dur-hover) var(--ease-pop);
}

@media (hover: hover) {
    .qr-btn:hover:not(:disabled) {
        background: var(--color-primary-a20);
        border-color: var(--color-primary-a30);
        color: var(--color-text-1);
    }
}

.qr-btn:active:not(:disabled) {
    transform: scale(0.97);
    transition-duration: var(--dur-press);
}

.qr-btn:disabled { opacity: 0.4; cursor: not-allowed; }

.qr-btn--primary {
    background: var(--color-selected-2);
    border-color: var(--color-selected-2);
    color: #ffffff;
    padding: 8px 18px;
    font-size: 13px;
}

@media (hover: hover) {
    .qr-btn--primary:hover:not(:disabled) {
        background: var(--color-selected-3);
        border-color: var(--color-selected-3);
        color: #06121e;
    }
}

.qr-btn--accent { color: var(--color-accent-text); border-color: var(--color-selected-1); }

@media (hover: hover) {
    .qr-btn--accent:hover:not(:disabled) {
        background: rgba(91, 148, 198, 0.14);
        border-color: var(--color-selected-2);
        color: var(--color-accent-text);
    }
}

.qr-btn--wide { width: 100%; }
.qr-btn--big { min-height: 42px; font-size: 14px; }

/* ---------------------------------------------------------------------------
   Layout

   Three areas rather than two columns. On a wide screen the preview sits on
   the right for the whole height and the content box and the settings stack
   on the left. On a phone it goes content, then preview, then settings, so
   the code you're making is always straight under whatever you just typed
   instead of a long scroll past every style option.
   --------------------------------------------------------------------------- */

.qr-body {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(300px, 400px);
    grid-template-areas:
        "content  preview"
        "settings preview";
    gap: 12px;
    padding: 12px;
    align-items: start;
}

.qr-col { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.qr-col--content { grid-area: content; }
.qr-col--settings { grid-area: settings; }
.qr-col--preview { grid-area: preview; align-self: stretch; }

.qr-sticky {
    position: sticky;
    top: 12px;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

@media (max-width: 900px) {
    .qr-body {
        grid-template-columns: minmax(0, 1fr);
        grid-template-areas:
            "content"
            "preview"
            "settings";
    }

    .qr-sticky { position: static; }
}

.qr-panel { background: var(--color-primary-a0); border: 1px solid var(--qr-border); border-radius: 12px; padding: 14px; min-width: 0; }

.qr-panel-title {
    display: block;
    margin: 0 0 12px;
    font-family: var(--qr-sans);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--color-primary-a30);
}

.qr-panel-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: 10px;
}

.qr-panel-head .qr-panel-title { margin: 0; }

.qr-panel-hint { margin: 10px 0 0; font-size: 11.5px; line-height: 1.55; color: var(--color-primary-a30); }
.qr-panel-hint:empty { display: none; }

/* ---------------------------------------------------------------------------
   Settings tabs

   Five tabs rather than five stacked panels. Stacked, the settings column
   ran to several screens and pushed everything below the fold, and on a
   desktop the sticky preview spent most of that scroll pinned beside things
   that had nothing to do with it.
   --------------------------------------------------------------------------- */

.qr-panel--tabs { padding: 0; }

.qr-tabs {
    display: flex;
    gap: 2px;
    padding: 6px 8px 0;
    border-bottom: 1px solid var(--qr-border);
    overflow-x: auto;
    scrollbar-width: none;
}

.qr-tabs::-webkit-scrollbar { display: none; }

.qr-tab {
    position: relative;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 11px 14px 12px;
    border: none;
    background: none;
    color: var(--color-text-2);
    font-family: var(--qr-sans);
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    border-radius: 8px 8px 0 0;
    transition: color var(--dur-hover) var(--ease-soft), background-color var(--dur-hover) var(--ease-soft);
}

.qr-tab::after {
    content: "";
    position: absolute;
    left: 10px;
    right: 10px;
    bottom: -1px;
    height: 3px;
    border-radius: 3px 3px 0 0;
    background: var(--color-selected-2);
    transform: scaleX(0);
    transition: transform var(--dur-hover) var(--ease-out);
}

@media (hover: hover) {
    .qr-tab:hover { color: var(--color-text-1); background: var(--color-primary-a10); }
}

.qr-tab[aria-selected="true"] { color: var(--color-text-1); }
.qr-tab[aria-selected="true"]::after { transform: scaleX(1); }

/* A small dot on Logo and Label once they're actually in use, so it's clear
   from any tab that something is switched on over there. */
.qr-tab-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--color-selected-3);
    display: none;
}

.qr-app.has-logo .qr-tab-dot[data-dot="logo"],
.qr-app.has-label .qr-tab-dot[data-dot="label"] { display: block; }

.qr-tabpanel { display: none; padding: 16px 14px; }

.qr-app[data-tab="shapes"] .qr-tabpanel[data-tab="shapes"],
.qr-app[data-tab="colours"] .qr-tabpanel[data-tab="colours"],
.qr-app[data-tab="logo"] .qr-tabpanel[data-tab="logo"],
.qr-app[data-tab="label"] .qr-tabpanel[data-tab="label"],
.qr-app[data-tab="size"] .qr-tabpanel[data-tab="size"] {
    display: block;
    animation: qr-tab-in 0.22s var(--ease-out);
}

@keyframes qr-tab-in { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }

@media (prefers-reduced-motion: reduce) {
    .qr-tabpanel { animation: none !important; }
}

.qr-section + .qr-section {
    margin-top: 18px;
    padding-top: 16px;
    border-top: 1px solid var(--qr-border);
}

.qr-section-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 12px;
}

.qr-section-head .qr-field-label { margin: 0; }

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

.qr-mini-label { font-size: 11.5px; color: var(--color-primary-a30); font-weight: 600; }

/* ---------------------------------------------------------------------------
   Segmented control — the pill-with-a-sliding-highlight look, used where a
   choice is between two to four short words.
   --------------------------------------------------------------------------- */

.qr-seg {
    display: inline-flex;
    flex-wrap: wrap;
    gap: 2px;
    padding: 3px;
    border-radius: 10px;
    background: var(--qr-surface);
    border: 1px solid var(--qr-border);
}

.qr-seg--wide { display: flex; }
.qr-seg--wide .qr-seg-opt { flex: 1; justify-content: center; }

.qr-seg-opt {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 6px 12px;
    border-radius: 7px;
    font-size: 12px;
    font-weight: 600;
    color: var(--color-text-2);
    cursor: pointer;
    white-space: nowrap;
    transition: background-color var(--dur-hover) var(--ease-soft), color var(--dur-hover) var(--ease-soft), box-shadow var(--dur-hover) var(--ease-soft);
}

.qr-seg-opt input {
    position: absolute;
    opacity: 0;
    width: 1px;
    height: 1px;
    margin: 0;
    pointer-events: none;
}

@media (hover: hover) {
    .qr-seg-opt:hover { color: var(--color-text-1); }
}

.qr-seg-opt:has(input:checked),
.qr-seg-opt.is-checked {
    background: var(--color-primary-a0);
    color: var(--color-text-1);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 0 0 1px var(--color-selected-2);
}

.qr-seg-opt:has(input:focus-visible) {
    outline: 2px solid var(--color-selected-3);
    outline-offset: 1px;
}

.qr-seg-hint { font-size: 10.5px; font-weight: 400; color: var(--color-primary-a30); }

/* ---------------------------------------------------------------------------
   Type picker — twelve kinds of code, icon over label.
   --------------------------------------------------------------------------- */

.qr-types {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(84px, 1fr));
    gap: 6px;
    margin-bottom: 14px;
}

.qr-type {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 5px;
    padding: 10px 6px 8px;
    border-radius: 10px;
    border: 1px solid var(--qr-border-strong);
    font-size: 11.5px;
    font-weight: 600;
    color: var(--color-text-2);
    text-align: center;
    cursor: pointer;
    transition:
        border-color var(--dur-hover) var(--ease-soft),
        background-color var(--dur-hover) var(--ease-soft),
        color var(--dur-hover) var(--ease-soft),
        transform var(--dur-hover) var(--ease-pop);
}

/* The radio itself is hidden but kept in the tree, so arrow keys still move
   between types and a screen reader still hears a radio group. */
.qr-type input {
    position: absolute;
    opacity: 0;
    width: 1px;
    height: 1px;
    margin: 0;
    pointer-events: none;
}

.qr-type svg {
    width: 22px;
    height: 22px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.8;
    stroke-linecap: round;
    stroke-linejoin: round;
}

@media (hover: hover) {
    .qr-type:hover { border-color: var(--color-selected-2); color: var(--color-text-1); }
}

.qr-type:active { transform: scale(0.97); transition-duration: var(--dur-press); }

.qr-type:has(input:checked),
.qr-type.is-checked {
    border-color: var(--color-selected-2);
    background: rgba(91, 148, 198, 0.16);
    color: var(--color-text-1);
}

.qr-type:has(input:focus-visible) {
    outline: 2px solid var(--color-selected-3);
    outline-offset: 2px;
}

/* ---------------------------------------------------------------------------
   Content fields — one block per type, only the chosen one shows.
   --------------------------------------------------------------------------- */

.qr-fields { display: none; }

.qr-app[data-type="link"]     .qr-fields[data-for="link"],
.qr-app[data-type="text"]     .qr-fields[data-for="text"],
.qr-app[data-type="wifi"]     .qr-fields[data-for="wifi"],
.qr-app[data-type="contact"]  .qr-fields[data-for="contact"],
.qr-app[data-type="email"]    .qr-fields[data-for="email"],
.qr-app[data-type="phone"]    .qr-fields[data-for="phone"],
.qr-app[data-type="sms"]      .qr-fields[data-for="sms"],
.qr-app[data-type="whatsapp"] .qr-fields[data-for="whatsapp"],
.qr-app[data-type="location"] .qr-fields[data-for="location"],
.qr-app[data-type="event"]    .qr-fields[data-for="event"],
.qr-app[data-type="file"]     .qr-fields[data-for="file"],
.qr-app[data-type="batch"]    .qr-fields[data-for="batch"] {
    display: block;
}

.qr-field { margin-bottom: 12px; }
.qr-field:last-child { margin-bottom: 0; }

.qr-field-label {
    display: block;
    margin-bottom: 8px;
    font-family: var(--qr-sans);
    font-size: 12px;
    font-weight: 600;
    color: var(--color-text-2);
}

.qr-field-row { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }

.qr-grid-2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 10px; }
.qr-grid-2 .qr-field:last-child { margin-bottom: 12px; }
.qr-grid-2--eyes { gap: 0 16px; }

@media (max-width: 520px) {
    .qr-grid-2 { grid-template-columns: minmax(0, 1fr); }
}

.qr-input,
.qr-select {
    width: 100%;
    box-sizing: border-box;
    padding: 8px 10px;
    border-radius: 8px;
    border: 1px solid var(--qr-border-strong);
    background: var(--color-primary-a0);
    color: var(--color-text-1);
    font-family: var(--qr-sans);
    font-size: 13px;
    line-height: 1.4;
    transition: border-color var(--dur-hover) var(--ease-soft), box-shadow var(--dur-hover) var(--ease-soft);
}

.qr-input:focus,
.qr-select:focus { border-color: var(--color-selected-2); box-shadow: 0 0 0 3px rgba(91, 148, 198, 0.18); outline: none; }

.qr-input::placeholder { color: var(--color-primary-a30); }

/* datetime-local draws its own calendar icon in black whatever the page
   says, which disappears on the dark theme. */
:root:not([data-theme="light"]) .qr-input[type="datetime-local"] { color-scheme: dark; }

.qr-textarea { resize: vertical; min-height: 72px; }
.qr-textarea--tall { min-height: 150px; font-family: var(--qr-mono); font-size: 12px; }

.qr-select { cursor: pointer; }

.qr-input-wrap { position: relative; }
.qr-input-wrap .qr-input { padding-right: 62px; }

.qr-input-btn {
    position: absolute;
    top: 50%;
    right: 5px;
    transform: translateY(-50%);
    padding: 4px 9px;
    border-radius: 6px;
    border: none;
    background: var(--qr-surface);
    color: var(--color-text-2);
    font-family: var(--qr-sans);
    font-size: 11px;
    font-weight: 600;
    cursor: pointer;
}

@media (hover: hover) {
    .qr-input-btn:hover { color: var(--color-text-1); background: var(--qr-surface-raised); }
}

/* ---------------------------------------------------------------------------
   Choice pills — same idiom as .ic-choice.
   --------------------------------------------------------------------------- */

.qr-choices { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; }
.qr-choices--tight { gap: 6px; }
.qr-choices--tight .qr-choice { padding: 6px 10px; }

.qr-choice {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 7px 12px;
    border-radius: 8px;
    border: 1px solid var(--qr-border-strong);
    font-family: var(--qr-sans);
    font-size: 12px;
    font-weight: 600;
    color: var(--color-text-2);
    cursor: pointer;
    transition:
        border-color var(--dur-hover) var(--ease-soft),
        background-color var(--dur-hover) var(--ease-soft),
        color var(--dur-hover) var(--ease-soft);
}

.qr-choice input { accent-color: var(--color-selected-2); margin: 0; }

.qr-choice-hint { color: var(--color-primary-a30); font-weight: 400; font-size: 11px; }

.qr-choice:has(input:checked),
.qr-choice.is-checked {
    border-color: var(--color-selected-2);
    background: rgba(91, 148, 198, 0.16);
    color: var(--color-text-1);
}

.qr-choice:has(input:disabled) { opacity: 0.45; }

/* ---------------------------------------------------------------------------
   Switches — every on/off setting. A checkbox dressed as a switch rather
   than a separate widget, so it keeps its label, its keyboard handling and
   what a screen reader says about it.
   --------------------------------------------------------------------------- */

.qr-checkbox-row {
    display: flex;
    align-items: center;
    gap: 9px;
    font-family: var(--qr-sans);
    font-size: 12.5px;
    color: var(--color-text-2);
    cursor: pointer;
    margin-bottom: 10px;
}

.qr-checkbox-row:last-child { margin-bottom: 0; }

.qr-checkbox-row input[type="checkbox"] {
    -webkit-appearance: none;
    appearance: none;
    position: relative;
    flex-shrink: 0;
    width: 32px;
    height: 18px;
    margin: 0;
    border-radius: 9px;
    background: var(--color-primary-a30);
    cursor: pointer;
    transition: background-color var(--dur-hover) var(--ease-soft);
}

.qr-checkbox-row input[type="checkbox"]::before {
    content: "";
    position: absolute;
    top: 2px;
    left: 2px;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: #ffffff;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.35);
    transition: transform var(--dur-hover) var(--ease-pop);
}

.qr-checkbox-row input[type="checkbox"]:checked { background: var(--color-selected-2); }
.qr-checkbox-row input[type="checkbox"]:checked::before { transform: translateX(14px); }
.qr-checkbox-row input[type="checkbox"]:focus-visible { outline: 2px solid var(--color-selected-3); outline-offset: 2px; }
.qr-checkbox-row:has(input:disabled) { opacity: 0.55; }

/* ---------------------------------------------------------------------------
   Sliders — the part left of the thumb fills in, so the value reads at a
   glance. --fill is set by the script as the slider moves.
   --------------------------------------------------------------------------- */

.qr-range {
    flex: 1;
    min-width: 80px;
    -webkit-appearance: none;
    appearance: none;
    height: 5px;
    border-radius: 3px;
    background: linear-gradient(to right, var(--color-selected-2) var(--fill, 50%), var(--qr-border-strong) var(--fill, 50%));
    cursor: pointer;
}

.qr-range::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: #ffffff;
    border: 3px solid var(--color-selected-2);
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.35);
    cursor: pointer;
    transition: transform var(--dur-hover) var(--ease-pop);
}

.qr-range::-moz-range-thumb {
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background: #ffffff;
    border: 3px solid var(--color-selected-2);
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.35);
    cursor: pointer;
}

.qr-range:active::-webkit-slider-thumb { transform: scale(1.15); }

/* Bigger grab target on touch, same reasoning as the image compressor's. */
@media (pointer: coarse) {
    .qr-range { height: 8px; }
    .qr-range::-webkit-slider-thumb { width: 26px; height: 26px; }
    .qr-range::-moz-range-thumb { width: 20px; height: 20px; }
}

.qr-number {
    width: 56px;
    flex-shrink: 0;
    box-sizing: border-box;
    padding: 5px 6px;
    border-radius: 6px;
    border: 1px solid var(--qr-border-strong);
    background: var(--color-primary-a0);
    color: var(--color-text-1);
    font-family: var(--qr-mono);
    font-size: 12px;
    text-align: center;
}

.qr-number--wide { width: 84px; }
.qr-output { display: inline-flex; align-items: center; justify-content: center; border-color: transparent; background: var(--qr-surface); }
.qr-unit { font-size: 11px; color: var(--color-primary-a30); }

/* ---------------------------------------------------------------------------
   Colour buttons — a chip and the hex, one click opens the picker.
   --------------------------------------------------------------------------- */

.qr-colour-btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-height: 36px;
    padding: 4px 12px 4px 4px;
    border-radius: 10px;
    border: 1px solid var(--qr-border-strong);
    background: var(--color-primary-a0);
    color: var(--color-text-1);
    font-family: var(--qr-mono);
    font-size: 12px;
    cursor: pointer;
    transition: border-color var(--dur-hover) var(--ease-soft), box-shadow var(--dur-hover) var(--ease-soft);
}

.qr-colour-chip {
    width: 28px;
    height: 28px;
    border-radius: 7px;
    box-shadow: inset 0 0 0 1px rgba(128, 128, 128, 0.4);
}

@media (hover: hover) {
    .qr-colour-btn:hover { border-color: var(--color-selected-2); }
}

.qr-colour-btn.is-open { border-color: var(--color-selected-2); box-shadow: 0 0 0 3px rgba(91, 148, 198, 0.22); }

.qr-solid { display: flex; align-items: center; flex-wrap: wrap; gap: 12px; }

.qr-quick { display: flex; flex-wrap: wrap; gap: 6px; }

.qr-quick-swatch {
    width: 24px;
    height: 24px;
    padding: 0;
    border-radius: 50%;
    border: none;
    box-shadow: inset 0 0 0 1px rgba(128, 128, 128, 0.45);
    cursor: pointer;
    transition: transform var(--dur-hover) var(--ease-pop), box-shadow var(--dur-hover) var(--ease-soft);
}

@media (hover: hover) {
    .qr-quick-swatch:hover { transform: scale(1.12); }
}

.qr-quick-swatch.is-current { box-shadow: inset 0 0 0 1px rgba(128, 128, 128, 0.45), 0 0 0 2px var(--color-primary-a0), 0 0 0 4px var(--color-selected-2); }

/* ---------------------------------------------------------------------------
   Gradient editor

   The pad on the left is the gradient laid over the real code, with a dial
   on top: drag round it to point a linear gradient, or drag the centre of a
   radial one. The compass next to it is the eight directions people
   actually want, one tap each. Under both, the bar is the gradient flattened
   out, with a marker per colour.
   --------------------------------------------------------------------------- */

.qr-app[data-fill="solid"] .qr-grad { display: none; }
.qr-app:not([data-fill="solid"]) .qr-solid { display: none; }
.qr-app[data-fill="radial"] .qr-compass { display: none; }
.qr-app:not([data-fill="radial"]) .qr-radial-tools { display: none; }

.qr-grad-main {
    display: grid;
    grid-template-columns: minmax(0, 170px) minmax(0, 1fr);
    gap: 16px;
    align-items: center;
}

@media (max-width: 400px) {
    .qr-grad-main { grid-template-columns: minmax(0, 1fr); }
}

.qr-pad {
    position: relative;
    aspect-ratio: 1 / 1;
    border-radius: 14px;
    cursor: crosshair;
    touch-action: none;
    user-select: none;
    -webkit-user-select: none;
    background-image:
        linear-gradient(45deg, var(--qr-checker-a) 25%, transparent 25%),
        linear-gradient(-45deg, var(--qr-checker-a) 25%, transparent 25%),
        linear-gradient(45deg, transparent 75%, var(--qr-checker-a) 75%),
        linear-gradient(-45deg, transparent 75%, var(--qr-checker-a) 75%);
    background-color: var(--qr-checker-b);
    background-size: 14px 14px;
    background-position: 0 0, 0 7px, 7px -7px, -7px 0px;
    box-shadow: inset 0 0 0 1px var(--qr-border);
}

.qr-pad:focus-visible { outline: 2px solid var(--color-selected-3); outline-offset: 3px; }

.qr-pad-inner { position: absolute; inset: 9%; }

.qr-pad-field {
    position: absolute;
    inset: -10%;
    border-radius: 12px;
    opacity: 0.3;
}

.qr-pad-code { position: absolute; inset: 0; }
.qr-pad-code svg { display: block; width: 100%; height: 100%; }

.qr-pad-guide {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    overflow: visible;
    pointer-events: none;
}

.qr-pad-handle {
    position: absolute;
    width: 20px;
    height: 20px;
    margin: -10px 0 0 -10px;
    border-radius: 50%;
    background: #ffffff;
    border: 3px solid var(--color-selected-2);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.5);
    pointer-events: none;
    transition: transform var(--dur-hover) var(--ease-pop);
}

.qr-pad.is-dragging .qr-pad-handle { transform: scale(1.2); }

.qr-grad-side { display: flex; flex-direction: column; align-items: flex-start; gap: 12px; }

.qr-compass {
    display: grid;
    grid-template-columns: repeat(3, 34px);
    grid-auto-rows: 34px;
    gap: 4px;
}

.qr-compass-btn {
    border-radius: 8px;
    border: 1px solid var(--qr-border-strong);
    background: var(--color-primary-a0);
    color: var(--color-text-2);
    font-size: 15px;
    line-height: 1;
    cursor: pointer;
    transition: border-color var(--dur-hover) var(--ease-soft), background-color var(--dur-hover) var(--ease-soft), color var(--dur-hover) var(--ease-soft);
}

@media (hover: hover) {
    .qr-compass-btn:hover { border-color: var(--color-selected-2); color: var(--color-text-1); }
}

.qr-compass-btn.is-current { background: var(--color-selected-2); border-color: var(--color-selected-2); color: #ffffff; }

.qr-compass-readout,
.qr-radial-readout {
    display: grid;
    place-items: center;
    font-family: var(--qr-mono);
    font-size: 11.5px;
    color: var(--color-text-1);
}

.qr-radial-tools { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; }
.qr-radial-readout { place-items: start; color: var(--color-text-2); }

.qr-grad-bar {
    position: relative;
    height: 30px;
    margin: 18px 11px 0;
}

.qr-grad-track {
    position: absolute;
    inset: 0 -11px;
    border-radius: 9px;
    box-shadow: inset 0 0 0 1px rgba(128, 128, 128, 0.35);
    cursor: copy;
}

.qr-stop {
    position: absolute;
    top: 50%;
    width: 22px;
    height: 38px;
    margin: -19px 0 0 -11px;
    padding: 0;
    border-radius: 8px;
    border: 3px solid #ffffff;
    background: var(--stop, #000);
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.4), 0 2px 6px rgba(0, 0, 0, 0.4);
    cursor: grab;
    touch-action: none;
    transition: transform var(--dur-hover) var(--ease-pop), box-shadow var(--dur-hover) var(--ease-soft);
}

.qr-stop:active { cursor: grabbing; }

.qr-stop.is-selected {
    transform: scale(1.12);
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.4), 0 0 0 4px var(--color-selected-3), 0 3px 10px rgba(0, 0, 0, 0.45);
    z-index: 1;
}

.qr-stop:focus-visible { outline: none; box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.4), 0 0 0 4px var(--color-selected-3); }

.qr-stop-row {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 16px;
}

.qr-stop-pos { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--color-text-2); }

.qr-presets-label { margin-top: 16px; }

.qr-grad-presets {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(62px, 1fr));
    gap: 8px;
}

.qr-grad-preset {
    display: flex;
    flex-direction: column;
    gap: 5px;
    padding: 0;
    border: none;
    background: none;
    color: var(--color-text-2);
    font-family: var(--qr-sans);
    font-size: 10.5px;
    font-weight: 600;
    cursor: pointer;
}

.qr-grad-preset span:first-child {
    display: block;
    height: 26px;
    border-radius: 8px;
    box-shadow: inset 0 0 0 1px rgba(128, 128, 128, 0.35);
    transition: transform var(--dur-hover) var(--ease-pop), box-shadow var(--dur-hover) var(--ease-soft);
}

@media (hover: hover) {
    .qr-grad-preset:hover { color: var(--color-text-1); }
    .qr-grad-preset:hover span:first-child { transform: translateY(-2px); }
}

.qr-grad-preset.is-current span:first-child { box-shadow: 0 0 0 2px var(--color-primary-a0), 0 0 0 4px var(--color-selected-2); }

.qr-app:not(.eyes-custom) .qr-eye-colours-row { display: none; }

.qr-contrast {
    margin: 12px 0 0;
    padding: 8px 10px;
    border-radius: 8px;
    font-size: 11.5px;
    line-height: 1.5;
    color: var(--color-text-2);
    background: var(--qr-surface);
}

.qr-contrast:empty { display: none; }
.qr-contrast[data-tone="warn"] { background: rgba(224, 160, 48, 0.12); }
.qr-contrast[data-tone="bad"] { background: rgba(231, 140, 140, 0.14); }
.qr-contrast strong { color: var(--color-text-1); }

/* ---------------------------------------------------------------------------
   File drop zone
   --------------------------------------------------------------------------- */

.qr-drop {
    padding: 22px 16px;
    border: 2px dashed var(--qr-border-strong);
    border-radius: 12px;
    text-align: center;
    color: var(--color-text-2);
    font-size: 13px;
    line-height: 1.6;
    transition:
        border-color var(--dur-hover) var(--ease-soft),
        background-color var(--dur-hover) var(--ease-soft);
}

.qr-app.is-dragging-file .qr-drop {
    border-color: var(--color-selected-2);
    background: rgba(91, 148, 198, 0.1);
}

.qr-drop strong { display: block; color: var(--color-text-1); font-size: 15px; margin-bottom: 6px; }
.qr-drop-hint { display: block; margin-top: 10px; font-size: 12px; color: var(--color-primary-a30); }

.qr-app.has-file .qr-drop { display: none; }

.qr-file-info {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    border-radius: 10px;
    border: 1px solid var(--color-selected-2);
    background: rgba(91, 148, 198, 0.1);
}

.qr-file-info[hidden] { display: none; }

.qr-file-name {
    flex: 1;
    min-width: 0;
    font-size: 12.5px;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ---------------------------------------------------------------------------
   Meters — how full the code is, and how much error correction the logo is
   using up. Same bar, two jobs. data-level turns it amber then red.
   --------------------------------------------------------------------------- */

.qr-meter-wrap { margin-top: 14px; }

.qr-meter {
    height: 6px;
    border-radius: 3px;
    background: var(--qr-border-strong);
    overflow: hidden;
}

.qr-meter-bar {
    width: 0%;
    height: 100%;
    border-radius: inherit;
    background: var(--color-selected-2);
    transition: width 0.2s var(--ease-out), background-color 0.2s var(--ease-soft);
}

.qr-meter-bar[data-level="warn"] { background: #e0a030; }
.qr-meter-bar[data-level="bad"] { background: var(--color-warning-1); }

.qr-meter-text { margin: 6px 0 0; font-size: 11.5px; line-height: 1.5; color: var(--color-text-2); }

.qr-meter--budget { margin-top: 2px; }

/* ---------------------------------------------------------------------------
   "What actually goes in the code"
   --------------------------------------------------------------------------- */

.qr-raw { margin-top: 12px; }

.qr-raw summary {
    font-size: 12px;
    font-weight: 600;
    color: var(--color-text-2);
    cursor: pointer;
    width: fit-content;
}

.qr-raw pre {
    margin: 8px 0 0;
    padding: 10px 12px;
    max-height: 180px;
    overflow: auto;
    border-radius: 8px;
    background: var(--qr-surface);
    border: 1px solid var(--qr-border);
    font-family: var(--qr-mono);
    font-size: 11.5px;
    line-height: 1.5;
    color: var(--color-text-1);
    white-space: pre-wrap;
    word-break: break-all;
}

/* ---------------------------------------------------------------------------
   Preview stage
   --------------------------------------------------------------------------- */

.qr-stage {
    position: relative;
    display: grid;
    place-items: center;
    min-height: 240px;
    padding: 16px;
    border-radius: 10px;
    background-image:
        linear-gradient(45deg, var(--qr-checker-a) 25%, transparent 25%),
        linear-gradient(-45deg, var(--qr-checker-a) 25%, transparent 25%),
        linear-gradient(45deg, transparent 75%, var(--qr-checker-a) 75%),
        linear-gradient(-45deg, transparent 75%, var(--qr-checker-a) 75%);
    background-color: var(--qr-checker-b);
    background-size: 20px 20px;
    background-position: 0 0, 0 10px, 10px -10px, -10px 0px;
    transition: background-color var(--dur-hover) var(--ease-soft), box-shadow var(--dur-hover) var(--ease-soft);
}

.qr-stage[data-backdrop="light"] { background-image: none; background-color: #f4f4f4; }
.qr-stage[data-backdrop="dark"] { background-image: none; background-color: #121418; }

.qr-backdrops { display: flex; gap: 4px; }

.qr-backdrop-btn {
    width: 22px;
    height: 22px;
    padding: 0;
    border-radius: 6px;
    border: 1px solid var(--qr-border-strong);
    cursor: pointer;
    transition: box-shadow var(--dur-hover) var(--ease-soft);
}

.qr-backdrop-btn[data-backdrop="checker"] {
    background: conic-gradient(#5c5c5c 25%, #4a4a4a 0 50%, #5c5c5c 0 75%, #4a4a4a 0) 0 0 / 10px 10px;
}

.qr-backdrop-btn[data-backdrop="light"] { background: #f4f4f4; }
.qr-backdrop-btn[data-backdrop="dark"] { background: #121418; }
.qr-backdrop-btn.is-current { box-shadow: 0 0 0 2px var(--color-primary-a0), 0 0 0 4px var(--color-selected-2); }

.qr-preview { width: 100%; display: grid; place-items: center; }

.qr-preview svg {
    display: block;
    width: 100%;
    height: auto;
    max-height: 62vh;
    filter: drop-shadow(0 4px 14px rgba(0, 0, 0, 0.35));
}

.qr-app.is-invalid .qr-preview { opacity: 0.18; filter: grayscale(1); }

.qr-stage-empty {
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
    margin: 0;
    padding: 24px;
    text-align: center;
    font-size: 13px;
    font-weight: 600;
    color: #ffffff;
    text-shadow: 0 1px 4px rgba(0, 0, 0, 0.6);
}

.qr-stage-empty[hidden] { display: none; }

.qr-drop-cover {
    position: absolute;
    inset: 0;
    display: none;
    place-items: center;
    border-radius: inherit;
    background: rgba(29, 34, 41, 0.72);
    box-shadow: inset 0 0 0 3px var(--color-selected-3);
    color: #ffffff;
    font-size: 14px;
    font-weight: 700;
}

.qr-app.is-dragging-logo .qr-drop-cover { display: grid; }

/* The live scan check. Off entirely when the browser has no BarcodeDetector. */
.qr-scan {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 10px 0 0;
    font-size: 12px;
    font-weight: 600;
    color: var(--color-text-2);
}

.qr-scan::before {
    content: "";
    width: 9px;
    height: 9px;
    flex-shrink: 0;
    border-radius: 50%;
    background: var(--color-primary-a30);
}

.qr-scan[data-state="ok"]::before { background: #4ade80; box-shadow: 0 0 0 3px rgba(74, 222, 128, 0.2); }
.qr-scan[data-state="fail"]::before { background: var(--color-warning-1); box-shadow: 0 0 0 3px rgba(231, 140, 140, 0.2); }
.qr-scan[data-state="pending"]::before { animation: qr-pulse 0.9s ease-in-out infinite alternate; }
.qr-scan[data-state="off"] { font-weight: 400; color: var(--color-primary-a30); }
.qr-scan:empty { display: none; }

@keyframes qr-pulse { from { opacity: 0.35; } to { opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
    .qr-scan[data-state="pending"]::before { animation: none; }
}

.qr-caution {
    margin: 12px 0 0;
    padding: 9px 11px;
    border-radius: 8px;
    border-left: 3px solid var(--color-warning-2);
    background: rgba(231, 140, 140, 0.1);
    font-size: 11.5px;
    line-height: 1.55;
    color: var(--color-text-2);
}

.qr-caution[data-tone="warn"] { border-left-color: #e0a030; background: rgba(224, 160, 48, 0.1); }
.qr-caution strong { color: var(--color-text-1); }
.qr-caution[hidden] { display: none; }

/* ---------------------------------------------------------------------------
   Download panel
   --------------------------------------------------------------------------- */

.qr-format-hint { margin: -2px 0 14px; }

.qr-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.qr-actions .qr-btn:not(.qr-btn--wide) { flex: 1 1 auto; }

.qr-sizes { display: flex; flex-wrap: wrap; gap: 4px; }

.qr-size-btn {
    padding: 4px 8px;
    border-radius: 6px;
    border: 1px solid var(--qr-border-strong);
    background: none;
    color: var(--color-text-2);
    font-family: var(--qr-mono);
    font-size: 11px;
    cursor: pointer;
    transition: border-color var(--dur-hover) var(--ease-soft), color var(--dur-hover) var(--ease-soft);
}

@media (hover: hover) {
    .qr-size-btn:hover { border-color: var(--color-selected-2); color: var(--color-text-1); }
}

.qr-size-btn.is-current { border-color: var(--color-selected-2); color: var(--color-text-1); background: rgba(91, 148, 198, 0.16); }

/* Pixel size is for the raster formats and SVG's own width attribute, print
   size is for the two page formats, and plain text has neither. */
.qr-app:not(:is([data-format="png"], [data-format="jpeg"], [data-format="webp"], [data-format="svg"])) .qr-px-row { display: none; }
.qr-app[data-format="svg"] .qr-px-row .qr-checkbox-row { display: none; }
.qr-app:not(:is([data-format="pdf"], [data-format="eps"])) .qr-mm-row { display: none; }

.qr-app:not([data-format="svg"]) #qr-copy-svg { display: none; }
.qr-app[data-format="txt"] #qr-copy { display: none; }

.qr-app[data-type="batch"] :is(#qr-download, #qr-copy, #qr-copy-svg) { display: none; }
.qr-app:not([data-type="batch"]) #qr-download-batch { display: none; }

.qr-app.is-invalid :is(#qr-download, #qr-download-batch, #qr-copy, #qr-copy-svg) { opacity: 0.4; pointer-events: none; }
.qr-app.is-busy :is(#qr-download, #qr-download-batch) { opacity: 0.6; pointer-events: none; }

/* ---------------------------------------------------------------------------
   Looks and shape pickers — both draw a real little QR code as their icon
   (qr-generator.js fills the art in), so what the button shows is exactly
   what clicking it gets you.
   --------------------------------------------------------------------------- */

.qr-looks {
    display: grid;
    grid-template-columns: repeat(6, minmax(58px, 1fr));
    gap: 8px;
    overflow-x: auto;
    padding: 2px;
    margin: -2px;
    scrollbar-width: thin;
}

.qr-look-btn {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    padding: 7px 6px 6px;
    border-radius: 10px;
    border: 1px solid var(--qr-border-strong);
    background: var(--color-primary-a0);
    cursor: pointer;
    transition:
        border-color var(--dur-hover) var(--ease-soft),
        background-color var(--dur-hover) var(--ease-soft),
        transform var(--dur-hover) var(--ease-pop);
}

@media (hover: hover) {
    .qr-look-btn:hover { border-color: var(--color-selected-2); background: rgba(91, 148, 198, 0.1); transform: translateY(-2px); }
}

.qr-look-btn:active { transform: scale(0.96); transition-duration: var(--dur-press); }

.qr-look-art { display: block; width: 100%; max-width: 60px; aspect-ratio: 1 / 1; }
.qr-look-art svg { display: block; width: 100%; height: 100%; border-radius: 6px; }
.qr-look-name { font-size: 11px; font-weight: 700; color: var(--color-text-1); }

.qr-shapes {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(62px, 1fr));
    gap: 6px;
    margin-bottom: 14px;
}

.qr-shapes--eyes { grid-template-columns: repeat(auto-fill, minmax(44px, 1fr)); }

.qr-shape {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    padding: 7px 4px 6px;
    border-radius: 10px;
    border: 1px solid var(--qr-border-strong);
    cursor: pointer;
    color: var(--color-text-2);
    transition:
        border-color var(--dur-hover) var(--ease-soft),
        background-color var(--dur-hover) var(--ease-soft),
        color var(--dur-hover) var(--ease-soft);
}

.qr-shape input {
    position: absolute;
    opacity: 0;
    width: 1px;
    height: 1px;
    margin: 0;
    pointer-events: none;
}

.qr-shape-art { display: block; width: 32px; height: 32px; color: var(--color-text-1); }
.qr-shape-art svg { display: block; width: 100%; height: 100%; fill: currentColor; }
.qr-shape-name { font-size: 10.5px; font-weight: 600; }

@media (hover: hover) {
    .qr-shape:hover { border-color: var(--color-selected-2); color: var(--color-text-1); }
}

.qr-shape:has(input:checked),
.qr-shape.is-checked {
    border-color: var(--color-selected-2);
    background: rgba(91, 148, 198, 0.16);
    color: var(--color-text-1);
}

.qr-shape:has(input:focus-visible) {
    outline: 2px solid var(--color-selected-3);
    outline-offset: 2px;
}

/* Module size only means something for shapes that sit apart from each
   other. The connected ones fill their square by definition. */
.qr-app:is([data-shape="square"], [data-shape="rounded"], [data-shape="classy"]) .qr-scale-row { display: none; }

/* ---------------------------------------------------------------------------
   Logo
   --------------------------------------------------------------------------- */

.qr-logo-row { display: flex; align-items: center; gap: 12px; }

.qr-logo-thumb {
    width: 52px;
    height: 52px;
    flex-shrink: 0;
    border-radius: 10px;
    border: 1px dashed var(--qr-border-strong);
    background-color: var(--qr-surface);
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center;
}

.qr-app.has-logo .qr-logo-thumb {
    border-style: solid;
    background-color: var(--qr-checker-b);
}

.qr-logo-buttons { display: flex; flex-wrap: wrap; gap: 8px; }

.qr-app:not(.has-logo) [data-needs-logo] { display: none; }
.qr-app.has-logo [data-hides-with-logo] { display: none; }
.qr-app[data-plate="none"] .qr-plate-colour { display: none; }

/* The wrap switch only means anything for a logo that's actually see-through.
   With a backing picked it stays visible but greyed out, with the note under
   it saying why, so it doesn't just vanish for no visible reason. */
.qr-app:not(.logo-has-alpha) :is(.qr-wrap-row, .qr-wrap-note) { display: none; }
.qr-wrap-note { margin: -4px 0 12px; }

/* ---------------------------------------------------------------------------
   Label — font cards show an "Aa" in the font itself.
   --------------------------------------------------------------------------- */

.qr-fonts {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 6px;
    margin-bottom: 12px;
}

.qr-font {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    padding: 8px 4px 7px;
    border-radius: 10px;
    border: 1px solid var(--qr-border-strong);
    color: var(--color-text-2);
    cursor: pointer;
    transition: border-color var(--dur-hover) var(--ease-soft), background-color var(--dur-hover) var(--ease-soft), color var(--dur-hover) var(--ease-soft);
}

.qr-font input {
    position: absolute;
    opacity: 0;
    width: 1px;
    height: 1px;
    margin: 0;
    pointer-events: none;
}

.qr-font-sample {
    font-size: 22px;
    line-height: 1.15;
    color: var(--color-text-1);
    max-width: 100%;
    overflow: hidden;
    white-space: nowrap;
}

.qr-font-name { font-size: 10.5px; font-weight: 600; }

@media (hover: hover) {
    .qr-font:hover { border-color: var(--color-selected-2); color: var(--color-text-1); }
}

.qr-font:has(input:checked),
.qr-font.is-checked {
    border-color: var(--color-selected-2);
    background: rgba(91, 148, 198, 0.16);
    color: var(--color-text-1);
}

.qr-font:has(input:focus-visible) { outline: 2px solid var(--color-selected-3); outline-offset: 2px; }

.qr-custom-font { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; }
.qr-font-file { font-size: 12px; color: var(--color-text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }

.qr-app:not([data-label-font="custom"]) :is(.qr-custom-font, .qr-custom-font-hint) { display: none; }

/* ---------------------------------------------------------------------------
   Location and advanced toggles
   --------------------------------------------------------------------------- */

.qr-app:not([data-geo="coords"]) .qr-geo-coords-row { display: none; }
.qr-app[data-geo="coords"] .qr-geo-address-row { display: none; }

.qr-app:not(.adv-open) .qr-advanced-body { display: none; }

.qr-advanced-toggle {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    margin-top: 4px;
    padding: 9px 12px;
    border-radius: 8px;
    border: 1px dashed var(--qr-border-strong);
    background: none;
    color: var(--color-text-2);
    font-family: var(--qr-sans);
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    transition: background-color var(--dur-hover) var(--ease-soft), color var(--dur-hover) var(--ease-soft);
}

@media (hover: hover) {
    .qr-advanced-toggle:hover { background: var(--color-primary-a10); color: var(--color-text-1); }
}

.qr-advanced-body { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--qr-border); }

/* ---------------------------------------------------------------------------
   Responsive
   --------------------------------------------------------------------------- */

@media (max-width: 480px) {
    .qr-types { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    .qr-body { padding: 8px; gap: 8px; }
    .qr-panel { padding: 12px; }
    .qr-panel--tabs { padding: 0; }
    .qr-tabpanel { padding: 14px 12px; }
    .qr-tab { padding: 10px 11px 11px; font-size: 12.5px; }
}

/* ===========================================================================
   COLOUR PICKER — appended to <body>, so nothing from .qr-app reaches it.
   A saturation/brightness square, a hue strip, the hex, and swatches.
   On a phone it becomes a sheet along the bottom of the screen instead of a
   popover that would be half off the edge.
   =========================================================================== */

.qr-picker {
    position: fixed;
    z-index: 1000;
    width: 252px;
    box-sizing: border-box;
    padding: 12px;
    border-radius: 14px;
    background: var(--color-primary-a0);
    border: 1px solid var(--color-card-border);
    box-shadow: 0 16px 40px rgba(0, 0, 0, 0.45), 0 2px 8px rgba(0, 0, 0, 0.25);
    font-family: "Circular Spotify", "Inter", sans-serif;
    color: var(--color-text-1);
    animation: qr-picker-in 0.16s var(--ease-out);
}

.qr-picker[hidden] { display: none; }

@keyframes qr-picker-in { from { opacity: 0; transform: translateY(-4px) scale(0.98); } to { opacity: 1; transform: none; } }

@media (prefers-reduced-motion: reduce) {
    .qr-picker { animation: none; }
}

.qr-picker.is-sheet {
    left: 0 !important;
    right: 0;
    top: auto !important;
    bottom: 0;
    width: auto;
    border-radius: 18px 18px 0 0;
    padding: 14px 16px calc(16px + env(safe-area-inset-bottom));
}

.qr-picker-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 10px;
    font-size: 12px;
    font-weight: 700;
    color: var(--color-text-2);
}

.qr-picker-close {
    width: 26px;
    height: 26px;
    border-radius: 7px;
    border: none;
    background: var(--color-primary-a10);
    color: var(--color-text-2);
    font-size: 16px;
    line-height: 1;
    cursor: pointer;
}

.qr-picker-close:hover { color: var(--color-text-1); }

.qr-picker-sv {
    position: relative;
    height: 150px;
    border-radius: 10px;
    background-color: hsl(var(--hue, 0) 100% 50%);
    background-image: linear-gradient(to top, #000000, transparent), linear-gradient(to right, #ffffff, rgba(255, 255, 255, 0));
    cursor: crosshair;
    touch-action: none;
}

.qr-picker.is-sheet .qr-picker-sv { height: 170px; }

.qr-picker-sv-thumb {
    position: absolute;
    width: 18px;
    height: 18px;
    margin: -9px 0 0 -9px;
    border-radius: 50%;
    border: 3px solid #ffffff;
    box-sizing: border-box;
    background: var(--now);
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.35), 0 2px 6px rgba(0, 0, 0, 0.4);
}

.qr-picker-sv-thumb:focus-visible { outline: 2px solid var(--color-selected-3); outline-offset: 2px; }

.qr-picker-hue {
    -webkit-appearance: none;
    appearance: none;
    display: block;
    width: 100%;
    height: 12px;
    margin: 12px 0;
    border-radius: 6px;
    background: linear-gradient(to right, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%);
    cursor: pointer;
}

.qr-picker-hue::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    border: 3px solid #ffffff;
    background: hsl(var(--hue, 0) 100% 50%);
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.35), 0 2px 5px rgba(0, 0, 0, 0.4);
}

.qr-picker-hue::-moz-range-thumb {
    width: 12px;
    height: 12px;
    border-radius: 50%;
    border: 3px solid #ffffff;
    background: hsl(var(--hue, 0) 100% 50%);
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.35);
}

.qr-picker-row { display: flex; align-items: center; gap: 8px; }

.qr-picker-now {
    width: 34px;
    height: 34px;
    flex-shrink: 0;
    border-radius: 8px;
    background: var(--now);
    box-shadow: inset 0 0 0 1px rgba(128, 128, 128, 0.45);
}

.qr-picker-hex {
    flex: 1;
    min-width: 0;
    box-sizing: border-box;
    padding: 8px 10px;
    border-radius: 8px;
    border: 1px solid var(--color-primary-a20);
    background: var(--color-primary-a10);
    color: var(--color-text-1);
    font-family: "JetBrains Mono", "Fira Mono", "Consolas", ui-monospace, monospace;
    font-size: 13px;
    text-transform: uppercase;
}

.qr-picker-hex:focus { outline: none; border-color: var(--color-selected-2); }
.qr-picker-hex.is-bad { border-color: var(--color-warning-1); }

.qr-picker-drop {
    width: 34px;
    height: 34px;
    flex-shrink: 0;
    display: grid;
    place-items: center;
    border-radius: 8px;
    border: 1px solid var(--color-primary-a20);
    background: none;
    color: var(--color-text-2);
    cursor: pointer;
}

.qr-picker-drop svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.qr-picker-drop:hover { color: var(--color-text-1); border-color: var(--color-selected-2); }
.qr-picker-drop[hidden] { display: none; }

.qr-picker-label {
    margin: 12px 0 6px;
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--color-primary-a30);
}

.qr-picker-label[hidden] { display: none; }

.qr-picker-swatches { display: grid; grid-template-columns: repeat(8, 1fr); gap: 6px; }

.qr-picker-swatch {
    aspect-ratio: 1 / 1;
    padding: 0;
    border-radius: 6px;
    border: none;
    box-shadow: inset 0 0 0 1px rgba(128, 128, 128, 0.45);
    cursor: pointer;
    transition: transform var(--dur-hover) var(--ease-pop);
}

.qr-picker-swatch:hover { transform: scale(1.12); }
.qr-picker-swatch.is-current { box-shadow: inset 0 0 0 1px rgba(128, 128, 128, 0.45), 0 0 0 2px var(--color-primary-a0), 0 0 0 4px var(--color-selected-2); }
.qr-picker-swatch:focus-visible { outline: 2px solid var(--color-selected-3); outline-offset: 2px; }

.qr-picker-done {
    display: none;
    width: 100%;
    margin-top: 14px;
    padding: 10px;
    border-radius: 10px;
    border: none;
    background: var(--color-selected-2);
    color: #ffffff;
    font-family: inherit;
    font-size: 14px;
    font-weight: 700;
    cursor: pointer;
}

.qr-picker.is-sheet .qr-picker-done { display: block; }

/* ===========================================================================
   MINI PREVIEW — phones only. Once the real preview has scrolled off the top
   of the screen while you're down in the settings, a small copy of the code
   sits in the bottom-left corner so every change is still visible. Tapping
   it scrolls back up. Bottom-left because the site's back-to-top button
   already owns bottom-right.
   =========================================================================== */

.qr-mini {
    position: fixed;
    left: 16px;
    bottom: calc(16px + env(safe-area-inset-bottom));
    z-index: 900;
    width: 88px;
    height: 88px;
    padding: 7px;
    box-sizing: border-box;
    border-radius: 16px;
    border: 1px solid var(--color-card-border);
    background: var(--color-primary-a10);
    box-shadow: 0 10px 28px rgba(0, 0, 0, 0.45);
    cursor: pointer;
    transform: translateY(calc(100% + 40px));
    transition: transform 0.3s var(--ease-out);
}

.qr-mini.is-visible { transform: none; }
.qr-mini svg { display: block; width: 100%; height: 100%; }
.qr-mini:focus-visible { outline: 2px solid var(--color-selected-3); outline-offset: 3px; }

@media (min-width: 901px) {
    .qr-mini { display: none; }
}
