/* ═══════════════════════════════════════════════════════════
   FONTEST — app.css
   ═══════════════════════════════════════════════════════════ */

/* ─── Variables ─────────────────────────────────────────── */
:root {
    /* ─── Primitives ─────────────────────────────────────── */
    --black: #000000;
    --white: #ffffff;
    --g50: #f7f7f7;
    --g100: #efefef;
    --g150: #e8e8e8;
    --g200: #dedede;
    --g300: #c8c8c8;
    --g400: #aaaaaa;
    --g500: #888888;
    --g600: #666666;
    --g700: #444444;
    --g800: #222222;

    /* ─── Semantic tokens (light mode default) ───────────
       Anything that should flip in dark mode references these instead of
       primitives. Dark overrides live below in body[data-theme="dark"]. */
    --bg-workspace:  #f1f1f1;      /* canvas around glyph cell */
    --bg-glyphspace: var(--white); /* inside glyph cell */
    --bg-panel:      var(--white); /* sidebars, dock, header */
    --bg-elevated:   var(--white); /* popups, menus, popovers */
    --bg-input:      var(--white); /* input/textarea/select */
    --bg-input-error: #f5f5f5;
    --fg-default:    var(--black); /* main text */
    --fg-muted:      var(--g500);  /* secondary text */
    --fg-strong:     var(--g800);  /* emphasized text */
    --border-soft-c: var(--g200);
    --border-mid-c:  var(--g300);
    --border-strong-c: var(--black);
    --fg-glyph:      var(--black); /* filled-glyph paint in canvas + thumbnails */
    --emphasis-bg:   var(--black); /* primary buttons, active tool, checked boxes */
    --emphasis-fg:   var(--white); /* paired with emphasis-bg */
    --glyphline:     #2a2a2a;      /* ascender / baseline / descender / cell edges */
    --thumb-bg:      #efefef;      /* project card placeholder bg */
    --thumb-line-1:  #d4d4d4;
    --thumb-line-2:  #dedede;
    --thumb-line-3:  #e8e8e8;
    --thumb-circ-1:  #cecece;
    --thumb-circ-2:  #c4c4c4;
    --thumb-circ-3:  #d0d0d0;
    --thumb-circ-4:  #dcdcdc;
    --thumb-text:    #bcbcbc;
    --home-dot:      #c0c0c0;      /* home screen background polka-dots */

    --border: 1px solid var(--border-soft-c);
    --border-dark: 1px solid var(--border-strong-c);
    --border-mid: 1px solid var(--border-mid-c);

    --ff-display: "JetBrains Mono", monospace;
    --ff-body: "JetBrains Mono", monospace;

    --header-h: 64px;

    /* accent — orange (Tailwind orange-600 + variants) */
    --accent: #ea580c; /* 600 */
    --accent-strong: #c2410c; /* 700 */
    --accent-light: #fb923c; /* 400 */
    --accent-pale: #fff7ed; /* 50  */

    /* Hover affordance — Tailwind indigo-500. */
    --hover: #6366f1;

    /* button grid pattern */
    --btn-grid-light:
        linear-gradient(rgba(255, 255, 255, 0.16) 1px, transparent 1px),
        linear-gradient(90deg, rgba(255, 255, 255, 0.16) 1px, transparent 1px);
    --btn-grid-dark:
        linear-gradient(rgba(0, 0, 0, 0.08) 1px, transparent 1px),
        linear-gradient(90deg, rgba(0, 0, 0, 0.08) 1px, transparent 1px);
    --btn-grid-size: 14px 14px;
}

/* ─── Dark theme overrides ──────────────────────────────── */
body[data-theme="dark"] {
    /* Inverted gray scale — keeps the relative meaning of g50…g800
       intact (lightest → darkest in the LOCAL sense). All existing
       references to var(--gN) keep working without per-site edits. */
    --g50:  #0e0e0e;
    --g100: #161616;
    --g150: #1d1d1d;
    --g200: #262626;
    --g300: #333333;
    --g400: #555555;
    --g500: #888888;
    --g600: #aaaaaa;
    --g700: #cfcfcf;
    --g800: #eaeaea;

    --bg-workspace:  #0e0e0e;
    --bg-glyphspace: #1a1a1a;
    --bg-panel:      #161616;
    --bg-elevated:   #1d1d1d;
    --bg-input:      #1d1d1d;
    --bg-input-error: #2a1010;
    --fg-default:    #e5e5e5;
    --fg-muted:      #999999;
    --fg-strong:     #f5f5f5;
    --border-soft-c:   #262626;
    --border-mid-c:    #2e2e2e;
    --border-strong-c: #383838;
    /* Composite tokens MUST be re-declared in dark mode: nested var()
       substitution happens at the defining scope, so leaving them aliased
       to --border-*-c in :root bakes them to light-mode hex. */
    --border:      1px solid #262626;
    --border-mid:  1px solid #2e2e2e;
    --border-dark: 1px solid #383838;
    --fg-glyph:      #f5f5f5;
    --emphasis-bg:   #f5f5f5;
    --emphasis-fg:   #0a0a0a;
    --glyphline:     #c8c8c8;
    --thumb-bg:      #1e1e1e;
    --thumb-line-1:  #333333;
    --thumb-line-2:  #2c2c2c;
    --thumb-line-3:  #262626;
    --thumb-circ-1:  #383838;
    --thumb-circ-2:  #404040;
    --thumb-circ-3:  #343434;
    --thumb-circ-4:  #2a2a2a;
    --thumb-text:    #555555;
    --home-dot:      #2a2a2a;

    color-scheme: dark;
}

/* ─── Reset ─────────────────────────────────────────────── */
*,
*::before,
*::after {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
    border-radius: 0 !important;
}

html,
body {
    height: 100%;
    overflow: hidden;
    background: var(--g50);
    color: var(--fg-default);
    font-family: var(--ff-body);
    font-size: 14px;
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
}

body {
    display: flex;
    flex-direction: column;
}

/* ─── Phosphor icons sizing per context ─────────────────── */
.ph,
[class^="ph-"],
[class*=" ph-"] {
    display: inline-flex;
    line-height: 1;
}
.btn .ph {
    font-size: 16px;
}
.btn-sm .ph {
    font-size: 13px;
}
.btn-icon .ph {
    font-size: 14px;
}
.ws-tool .ph {
    font-size: 18px;
}
.layer-btn .ph {
    font-size: 13px;
}
.ctx-item .ph {
    font-size: 15px;
}
.dev-clear-btn .ph {
    font-size: 11px;
}
.collapsible-toggle .ph {
    font-size: 11px;
    transition: transform 120ms ease;
}
.collapsible.open .collapsible-toggle .ph {
    transform: rotate(90deg);
}
.prop-section-toggle .ph {
    font-size: 11px;
    transition: transform 120ms ease;
}
.prop-section.collapsible.open .prop-section-toggle .ph {
    transform: rotate(90deg);
}

/* ─── Scrollbars (dark neutral thumb, sidebar-tinted track) ─ */
* {
    scrollbar-width: thin;
    /* thumb | track — Firefox. Track matches the sidebar bg so the gutter
       blends into the panel chrome. */
    scrollbar-color: var(--g700) var(--bg-panel);
}
*::-webkit-scrollbar {
    width: 10px;
    height: 10px;
}
*::-webkit-scrollbar-track {
    background: var(--bg-panel);
}
*::-webkit-scrollbar-thumb {
    background: var(--g700);
    /* Inset border in track color trims the thumb to ~6px, leaving the
       track visible as a 2px frame around it. */
    border: 2px solid var(--bg-panel);
    background-clip: padding-box;
}
*::-webkit-scrollbar-thumb:hover  { background: var(--g800); background-clip: padding-box; }
*::-webkit-scrollbar-thumb:active { background: var(--emphasis-bg); background-clip: padding-box; }
*::-webkit-scrollbar-corner {
    background: var(--bg-panel);
}

button {
    cursor: pointer;
    font-family: var(--ff-body);
}
a {
    color: inherit;
    text-decoration: none;
}
svg {
    display: block;
    flex-shrink: 0;
}

/* ─── Dev Clear Button ──────────────────────────────────── */
.dev-clear-btn {
    position: fixed;
    top: 0;
    left: 50%;
    transform: translateX(-50%);
    z-index: 9000;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 12px 4px;
    background: var(--g700);
    color: var(--emphasis-fg);
    border: var(--border-dark);
    border-top: none;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.1em;
    opacity: 0.45;
    transition:
        opacity 0.12s,
        background 0.12s;
    background-image: var(--btn-grid-light);
    background-size: var(--btn-grid-size);
}
.dev-clear-btn:hover {
    opacity: 1;
    background-color: var(--emphasis-bg);
}

/* ─── Header ────────────────────────────────────────────── */
#app-header {
    flex-shrink: 0;
    z-index: 100;
    height: var(--header-h);
    background: var(--bg-panel);
    border-bottom: var(--border);
}

.header-content {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    height: 100%;
    padding: 0 24px;
    gap: 16px;
}
.header-content[hidden] {
    display: none !important;
}
.header-content > * {
    min-width: 0;
}
.header-content > .header-logo {
    grid-column: 1;
    justify-self: start;
}
.header-content > .header-project-title {
    grid-column: 2;
    justify-self: center;
}
.header-content > .header-right {
    grid-column: 3;
    justify-self: end;
}

.header-right {
    display: flex;
    align-items: center;
    gap: 10px;
}

.header-logo {
    font-family: var(--ff-display);
    font-size: 22px;
    font-weight: 700;
    letter-spacing: 0.04em;
    color: var(--fg-default);
    user-select: none;
    white-space: nowrap;
    text-decoration: none;
    cursor: pointer;
    transition: color 0.12s;
}
.header-logo:hover {
    color: var(--accent);
}

.header-sep {
    color: var(--g300);
    font-size: 20px;
    font-weight: 300;
    user-select: none;
}

.header-project-title {
    font-family: var(--ff-body);
    font-size: 14px;
    font-weight: 600;
    letter-spacing: 0.04em;
    color: var(--g700);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}

/* ─── Buttons ───────────────────────────────────────────── */
.btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    height: 40px;
    padding: 0 18px;
    border: var(--border-dark);
    font-family: var(--ff-body);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.09em;
    white-space: nowrap;
    transition:
        background-color 0.12s,
        box-shadow 0.12s,
        transform 0.1s;
    background-size: var(--btn-grid-size);
}

.btn-primary {
    background-color: var(--emphasis-bg);
    color: var(--emphasis-fg);
    background-image: var(--btn-grid-light);
}
.btn-primary:hover {
    background-color: var(--g800);
    box-shadow: 4px 4px 0 var(--black);
    transform: translate(-1px, -1px);
}
.btn-primary:active {
    transform: translate(0, 0);
    box-shadow: 1px 1px 0 var(--black);
}

.btn-secondary {
    background-color: var(--bg-panel);
    color: var(--fg-default);
    background-image: var(--btn-grid-dark);
}
.btn-secondary:hover {
    background-color: var(--g100);
    box-shadow: 4px 4px 0 var(--black);
    transform: translate(-1px, -1px);
}
.btn-secondary:active {
    transform: translate(0, 0);
    box-shadow: 1px 1px 0 var(--black);
}

.btn-sm {
    height: 32px;
    padding: 0 12px;
    font-size: 11px;
}

/* Icon-only square button (theme toggle and similar). Matches .btn height. */
.btn-icon-only {
    width: 40px;
    padding: 0;
    justify-content: center;
}
.btn-icon-only .ph { font-size: 18px; }
.btn-theme {
    background-color: var(--bg-panel);
    color: var(--fg-default);
}
.btn-theme:hover {
    background-color: var(--g100);
    box-shadow: 4px 4px 0 var(--black);
    transform: translate(-1px, -1px);
}
.btn-theme:active {
    transform: translate(0, 0);
    box-shadow: 1px 1px 0 var(--black);
}

/* ─── Screen system ─────────────────────────────────────── */
.screen {
    display: none;
}
.screen.active {
    display: flex;
    flex-direction: column;
    flex: 1;
}

/* ─── Main Content ──────────────────────────────────────── */
#main-content {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    background-color: var(--g50);
}

#screen-home.active {
    padding: 36px 24px 64px;
    background-image: radial-gradient(circle, var(--home-dot) 1px, transparent 1px);
    background-size: 26px 26px;
    overflow-y: auto;
    overflow-x: hidden;
}

#screen-workspace.active {
    position: relative;
    overflow: hidden;
    background: var(--bg-panel);
    padding: 0;
}

/* ─── Preview screen ────────────────────────────────────── */
#screen-preview.active {
    position: relative;
    display: flex;
    flex-direction: column;
    background: var(--bg-panel);
    padding: 0;
    overflow: hidden;
}
.preview-toolbar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: 16px;
    padding: 10px 20px;
    border-bottom: var(--border);
    background: var(--g50);
    flex-shrink: 0;
}
.preview-tools-left,
.preview-tools-right {
    display: flex;
    align-items: center;
    gap: 16px;
}
.preview-sample {
    height: 34px;
    padding: 0 10px;
    border: var(--border-mid);
    background: var(--bg-panel);
    color: var(--fg-default);
    font-family: var(--ff-body);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.08em;
    cursor: pointer;
}
.preview-ctrl {
    display: inline-flex;
    flex-direction: column;
    align-items: stretch;
    gap: 4px;
    min-width: 180px;
}
.preview-ctrl-label {
    font-family: var(--ff-body);
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.1em;
    color: var(--g600);
}
.preview-text {
    flex: 1;
    min-height: 0;
    width: 100%;
    border: none;
    outline: none;
    background: var(--bg-panel);
    color: var(--fg-default);
    padding: 32px 40px;
    resize: none;
    /* font-family + size + line-height are set inline at openPreviewScreen
       time so each visit picks up the latest font face. */
}
.preview-text::placeholder { color: var(--g300); }

/* ─── Project Grid ──────────────────────────────────────── */
.project-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr));
    gap: 20px;
    max-width: 1440px;
    margin: 0 auto;
    width: 100%;
}
.project-card {
    min-width: 0;
}

/* ─── Project Card ──────────────────────────────────────── */
.project-card {
    background: var(--bg-panel);
    border: var(--border-mid);
    cursor: pointer;
    transition:
        border-color 0.12s,
        box-shadow 0.12s,
        transform 0.1s;
    overflow: hidden;
    display: flex;
    flex-direction: column;
}
.project-card:hover {
    border-color: var(--fg-default);
    box-shadow: 4px 4px 0 var(--black);
    transform: translate(-1px, -1px);
}
.project-card:active {
    transform: translate(0, 0);
    box-shadow: 1px 1px 0 var(--black);
}

/* ─── Card Thumbnail ─────────────────────────────────────── */
.card-thumbnail {
    aspect-ratio: 16 / 9;
    overflow: hidden;
    border-bottom: var(--border);
    background: var(--g100);
    position: relative;
}
.card-thumbnail svg {
    width: 100%;
    height: 100%;
}

/* ─── Card Body ─────────────────────────────────────────── */
.card-body {
    padding: 14px 16px 15px;
    display: flex;
    flex-direction: column;
    gap: 10px;
    flex: 1;
}

.card-name {
    font-family: var(--ff-display);
    font-size: 16px;
    font-weight: 600;
    color: var(--fg-default);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    line-height: 1.4;
}

.card-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}

.card-date {
    font-size: 11px;
    color: var(--g500);
    letter-spacing: 0.03em;
}

.card-progress {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.06em;
    color: var(--g600);
    background: var(--g100);
    border: var(--border);
    padding: 3px 9px;
    line-height: 1.6;
}

/* ─── Popup System ──────────────────────────────────────── */
.popup-overlay {
    position: fixed;
    inset: 0;
    z-index: 500;
    background: rgba(0, 0, 0, 0.5);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
    animation: overlay-in 120ms ease;
}
.popup-overlay[hidden] {
    display: none !important;
}

@keyframes overlay-in {
    from {
        opacity: 0;
    }
    to {
        opacity: 1;
    }
}

.popup {
    background: var(--bg-elevated);
    border: var(--border-dark);
    width: 100%;
    max-width: 580px;
    max-height: calc(100vh - 48px);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    animation: popup-in 120ms ease;
}

.popup-overlay.closing {
    animation: overlay-out 120ms ease forwards;
}
.popup-overlay.closing .popup {
    animation: popup-out 120ms ease forwards;
}
@keyframes overlay-out {
    from {
        opacity: 1;
    }
    to {
        opacity: 0;
    }
}
@keyframes popup-out {
    from {
        opacity: 1;
        transform: translateY(0);
    }
    to {
        opacity: 0;
        transform: translateY(-6px);
    }
}

@keyframes popup-in {
    from {
        opacity: 0;
        transform: translateY(-8px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

.popup-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 16px 20px;
    flex-shrink: 0;
    background-image: var(--btn-grid-dark);
    background-size: var(--btn-grid-size);
    background-color: var(--g50);
}

.popup-title {
    font-family: var(--ff-display);
    font-size: 16px;
    letter-spacing: 0.08em;
    color: var(--fg-default);
}

.btn-icon {
    width: 30px;
    height: 30px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: var(--border);
    background: var(--bg-panel);
    color: var(--g500);
    cursor: pointer;
    transition:
        background 0.1s,
        color 0.1s;
    flex-shrink: 0;
}
.btn-icon:hover {
    background: var(--g100);
    color: var(--fg-default);
}
.btn-icon:active {
    opacity: 0.82;
}

.popup-body {
    padding: 22px 22px 10px;
    overflow-y: auto;
    flex: 1;
}

/* Import overview: key/value summary of the project being imported. */
.import-summary {
    display: flex;
    flex-direction: column;
    border: var(--border);
    background: var(--g50);
    margin-top: 4px;
}
.import-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 7px 10px;
    border-bottom: var(--border);
}
.import-row:last-child { border-bottom: none; }
.import-row-k {
    font-family: var(--ff-body);
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.1em;
    color: var(--g500);
}
.import-row-v {
    font-family: var(--ff-body);
    font-size: 11px;
    color: var(--fg-default);
    text-align: right;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Export popup: two big choice tiles (OTF / JSON), stacked. */
#popup-export .popup-body {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding-bottom: 22px;
}
.export-option {
    display: flex;
    align-items: center;
    gap: 14px;
    width: 100%;
    padding: 14px;
    background: var(--bg-panel);
    border: var(--border-mid);
    cursor: pointer;
    text-align: left;
    transition: background 0.1s, border-color 0.1s, transform 0.08s, box-shadow 0.08s;
}
.export-option:hover {
    background: var(--g50);
    border-color: var(--fg-default);
    transform: translate(-1px, -1px);
    box-shadow: 2px 2px 0 0 var(--black);
}
.export-option:active {
    transform: none;
    box-shadow: none;
}
.export-option-icon {
    width: 40px;
    height: 40px;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--emphasis-bg);
    color: var(--emphasis-fg);
}
.export-option-icon .ph { font-size: 20px; }
.export-option-text {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.export-option-title {
    font-family: var(--ff-display);
    font-size: 14px;
    font-weight: 700;
    letter-spacing: 0.1em;
    color: var(--fg-default);
}
.export-option-desc {
    font-family: var(--ff-body);
    font-size: 11px;
    color: var(--g500);
    line-height: 1.4;
}

.popup-footer {
    padding: 14px 22px;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 10px;
    flex-shrink: 0;
    background: var(--g50);
}

/* ─── Form Fields ───────────────────────────────────────── */
.field-group {
    display: flex;
    flex-direction: column;
    gap: 6px;
    flex: 1;
    min-width: 0;
    margin-bottom: 14px;
}
.field-group:last-child {
    margin-bottom: 0;
}

.field-section-title {
    font-family: var(--ff-body);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.1em;
    color: var(--g500);
    margin-bottom: 10px;
}

.field-row {
    display: flex;
    gap: 10px;
}

.field-label {
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.08em;
    color: var(--g600);
    user-select: none;
}

.field-hint {
    font-weight: 400;
    color: var(--g400);
    letter-spacing: 0.03em;
    font-size: 10px;
}
.btn + .field-hint,
.btn-sm + .field-hint {
    margin-top: 10px;
}
.prop-section .btn + .field-hint {
    margin-top: 8px;
}

.field-input {
    font-family: var(--ff-body);
    font-size: 13px;
    padding: 9px 11px;
    border: var(--border-mid);
    background: var(--bg-input);
    color: var(--fg-default);
    outline: none;
    width: 100%;
    transition: border-color 0.1s;
}
.field-input:focus {
    border-color: var(--fg-default);
}
.field-input.error {
    border-color: var(--accent);
    background: var(--bg-input-error);
}

input[type="number"].field-input {
    -moz-appearance: textfield;
}
input[type="number"].field-input::-webkit-inner-spin-button,
input[type="number"].field-input::-webkit-outer-spin-button {
    opacity: 0.4;
}

.field-textarea {
    resize: vertical;
    min-height: 78px;
    line-height: 1.7;
    letter-spacing: 0.04em;
}

/* Two-column field row — label-above-control in both columns, baselines
   align because both labels share .field-label styling. */
.field-row {
    display: flex;
    gap: 10px;
    align-items: stretch;
}
.field-col { flex: 1; min-width: 0; }
.field-col-fixed { flex: 0 0 64px; }

/* Custom color swatch button (replaces native input[type=color] so we can
   control popover placement inside the viewport). */
.field-color-btn {
    width: 100%;
    height: 36px;            /* matches .field-input total height */
    padding: 0;
    border: var(--border-mid);
    cursor: pointer;
    display: block;
}
.field-color-btn:focus {
    outline: 2px solid var(--accent);
    outline-offset: -2px;
}

/* Figma-style HSV color picker popover. */
.color-popover {
    background: var(--bg-elevated);
    border: var(--border-dark);
    box-shadow: 4px 4px 0 rgba(0, 0, 0, 0.12);
    padding: 8px;
    z-index: 200;
    display: flex;
    flex-direction: column;
    gap: 8px;
    user-select: none;
}

/* Saturation × value square. The hue layer is the bottom solid color; on top
   are two CSS gradients producing the standard "white at left, black at
   bottom" SV chart. */
.cp-sv {
    position: relative;
    width: 100%;
    height: 160px;
    border: var(--border-mid);
    cursor: crosshair;
    touch-action: none;
}
.cp-sv > .cp-sv-hue,
.cp-sv > .cp-sv-white,
.cp-sv > .cp-sv-black {
    position: absolute;
    inset: 0;
    pointer-events: none;
}
.cp-sv-hue   { background: hsl(0, 100%, 50%); }
.cp-sv-white { background: linear-gradient(to right, #fff, transparent); }
.cp-sv-black { background: linear-gradient(to top,   #000, transparent); }
.cp-sv-thumb {
    position: absolute;
    width: 12px;
    height: 12px;
    margin-left: -6px;
    margin-top:  -6px;
    border: 2px solid #fff;
    box-shadow: 0 0 0 1px #000;
    border-radius: 50%;
    pointer-events: none;
    background: #fff;
}

/* Hue strip. */
.cp-hue {
    position: relative;
    width: 100%;
    height: 14px;
    background: linear-gradient(to right,
        #ff0000 0%,
        #ffff00 17%,
        #00ff00 33%,
        #00ffff 50%,
        #0000ff 67%,
        #ff00ff 83%,
        #ff0000 100%);
    border: var(--border-mid);
    cursor: ew-resize;
    touch-action: none;
}
.cp-hue-thumb {
    position: absolute;
    top: -3px;
    bottom: -3px;
    width: 6px;
    margin-left: -3px;
    background: transparent;
    border: 2px solid #fff;
    box-shadow: 0 0 0 1px #000;
    pointer-events: none;
}

/* Alpha strip — checker bg shows transparency, gradient overlay paints from
   transparent → current color. */
.cp-alpha {
    position: relative;
    width: 100%;
    height: 14px;
    border: var(--border-mid);
    cursor: ew-resize;
    touch-action: none;
    overflow: hidden;
}
.cp-alpha-bg {
    position: absolute;
    inset: 0;
    background:
      conic-gradient(#ccc 25%, #fff 0 50%, #ccc 0 75%, #fff 0) 0 0 / 8px 8px;
    pointer-events: none;
}
.cp-alpha-grad {
    position: absolute;
    inset: 0;
    pointer-events: none;
}
.cp-alpha-thumb {
    position: absolute;
    top: -3px;
    bottom: -3px;
    width: 6px;
    margin-left: -3px;
    background: transparent;
    border: 2px solid #fff;
    box-shadow: 0 0 0 1px #000;
    pointer-events: none;
}

.cp-row { display: flex; gap: 6px; min-width: 0; }
.cp-hex {
    flex: 1 1 0;
    min-width: 0;       /* allow flex shrink below intrinsic input size */
    width: 0;           /* belt + braces — browsers vary on input shrink */
    font-family: var(--ff-body);
    font-size: 12px;
    padding: 6px 8px;
    border: var(--border-mid);
    background: var(--bg-panel);
    color: var(--fg-default);
    outline: none;
    text-transform: lowercase;
    letter-spacing: 0.04em;
}
.cp-hex:focus { border-color: var(--fg-default); }
.cp-opacity {
    flex: 0 0 64px;
    min-width: 0;
    width: 64px;
    font-family: var(--ff-body);
    font-size: 12px;
    padding: 6px 8px;
    border: var(--border-mid);
    background: var(--bg-panel);
    color: var(--fg-default);
    outline: none;
    text-align: right;
}
.cp-opacity:focus { border-color: var(--fg-default); }

.cp-presets {
    display: grid;
    grid-template-columns: repeat(10, 1fr);
    gap: 3px;
}
.cp-preset {
    width: 100%;
    aspect-ratio: 1;
    border: var(--border-mid);
    cursor: pointer;
    padding: 0;
}

.field-slider {
    width: 100%;
    appearance: none;
    -webkit-appearance: none;
    height: 2px;
    background: var(--g300);
    outline: none;
    cursor: pointer;
    margin: 6px 0;
}
.field-slider::-webkit-slider-thumb {
    appearance: none;
    -webkit-appearance: none;
    width: 12px;
    height: 12px;
    background: var(--emphasis-bg);
    cursor: pointer;
}
.field-slider::-moz-range-thumb {
    width: 12px;
    height: 12px;
    background: var(--emphasis-bg);
    border: none;
    cursor: pointer;
    border-radius: 0;
}

.field-meta {
    display: flex;
    align-items: center;
    justify-content: space-between;
    min-height: 16px;
}

.field-error {
    font-size: 10px;
    font-weight: 600;
    color: var(--g700);
    letter-spacing: 0.06em;
}

.field-count {
    font-size: 10px;
    color: var(--g400);
    letter-spacing: 0.06em;
    text-align: right;
    white-space: nowrap;
}

/* ─── Collapsible Section ───────────────────────────────── */
.collapsible {
    margin-top: 6px;
}

.collapsible-toggle {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 12px 2px;
    border: none;
    background: transparent;
    cursor: pointer;
    font-family: var(--ff-body);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.1em;
    color: var(--g500);
    text-align: left;
    transition: color 0.1s;
}
.collapsible-toggle:hover {
    color: var(--fg-default);
}
.collapsible-toggle:active {
    opacity: 0.7;
}
.collapsible-toggle svg {
    color: var(--g500);
    transition: transform 120ms ease;
}
.collapsible-toggle:hover svg {
    color: var(--fg-default);
}
.collapsible.open .collapsible-toggle svg {
    transform: rotate(90deg);
}

.collapsible-content {
    display: none;
    padding: 4px 0 16px;
}
.collapsible.open .collapsible-content {
    display: block;
}

/* ─── Empty State ───────────────────────────────────────── */
.empty-state {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 32px;
    text-align: center;
}

.empty-icon {
    width: 72px;
    height: 72px;
    border: var(--border-mid);
    background: var(--bg-panel);
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 24px;
    background-image: var(--btn-grid-dark);
    background-size: 8px 8px;
}

.empty-title {
    font-family: var(--ff-display);
    font-size: 16px;
    color: var(--g400);
    letter-spacing: 0.1em;
    margin-bottom: 10px;
}

.empty-sub {
    font-size: 12px;
    color: var(--g400);
    letter-spacing: 0.04em;
    max-width: 300px;
    line-height: 1.7;
}

/* ─── Context Menu ──────────────────────────────────────── */
.ctx-menu {
    position: fixed;
    z-index: 800;
    background: var(--bg-elevated);
    border: var(--border-dark);
    min-width: 190px;
    padding: 4px 0;
    box-shadow: 4px 4px 0 rgba(0, 0, 0, 0.12);
    animation: ctx-in 0.08s ease;
}
.ctx-menu[hidden] {
    display: none !important;
}

@keyframes ctx-in {
    from {
        opacity: 0;
        transform: scale(0.97);
    }
    to {
        opacity: 1;
        transform: scale(1);
    }
}

.ctx-item {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 9px 14px;
    background: none;
    border: none;
    font-family: var(--ff-body);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.07em;
    color: var(--fg-default);
    text-align: left;
    cursor: pointer;
    transition: background 0.08s;
    white-space: nowrap;
}
.ctx-item:hover {
    background: var(--g100);
}
.ctx-item:active {
    opacity: 0.7;
}
.ctx-item[disabled] {
    opacity: 0.45;
    cursor: not-allowed;
    pointer-events: none;
}
.ctx-item svg {
    color: var(--g500);
    flex-shrink: 0;
}

.ctx-item-delete {
    color: var(--g800);
}
.ctx-item-delete svg {
    color: var(--g600);
}
.ctx-item-delete:hover {
    background: var(--g150);
}

.ctx-divider {
    height: 1px;
    background: var(--g200);
    margin: 4px 0;
}

/* ─── Delete Confirmation ───────────────────────────────── */
.popup-sm {
    max-width: 380px;
}

.popup-body-confirm {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 28px 24px 20px;
    gap: 10px;
}

.confirm-icon {
    width: 52px;
    height: 52px;
    border: var(--border-mid);
    display: flex;
    align-items: center;
    justify-content: center;
    background-image: var(--btn-grid-dark);
    background-size: 8px 8px;
    background-color: var(--g50);
    margin-bottom: 4px;
}

.confirm-name {
    font-family: var(--ff-display);
    font-size: 14px;
    color: var(--fg-default);
    word-break: break-word;
}

.confirm-sub {
    font-size: 12px;
    color: var(--g500);
    letter-spacing: 0.04em;
}

/* ─── Workspace ─────────────────────────────────────────── */
.ws-body {
    display: flex;
    flex: 1;
    min-height: 0;
}

.ws-sidebar {
    display: flex;
    flex-direction: column;
    width: 240px;
    flex-shrink: 0;
    background: var(--bg-panel);
    min-height: 0;
}
.ws-sidebar-left {
    border-right: var(--border);
}
.ws-sidebar-right {
    border-left: var(--border);
    width: 280px;
}
/* Collapse hides the sidebar; the floating expand button takes over (see
   below). State is body-level so the canvas can re-layout in JS. */
body[data-left-collapsed="1"]  .ws-sidebar-left  { display: none; }
body[data-right-collapsed="1"] .ws-sidebar-right { display: none; }

/* Collapse button sits in the sidebar's top tab strip — square, 40px tall so
   it matches the strip's pinned height. */
.ws-sidebar-collapse {
    flex: 0 0 auto;
    width: 40px;
    height: 40px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: none;
    color: var(--g600);
    cursor: pointer;
    transition: color 0.12s, background 0.12s;
}
.ws-sidebar-collapse:hover { color: var(--fg-default); background: var(--g100); }
.ws-sidebar-collapse .ph   { font-size: 14px; }

/* Floating expand button — only visible when the matching sidebar is hidden.
   Pinned to the top corner just below the app header. */
.ws-sidebar-expand {
    position: absolute;
    top: 8px;
    z-index: 20;
    width: 32px;
    height: 32px;
    display: none;
    align-items: center;
    justify-content: center;
    background: var(--bg-panel);
    border: var(--border-mid);
    color: var(--g700);
    cursor: pointer;
    transition: color 0.12s, background 0.12s;
}
.ws-sidebar-expand[data-side="left"]  { left:  8px; }
.ws-sidebar-expand[data-side="right"] { right: 8px; }
.ws-sidebar-expand:hover { color: var(--fg-default); background: var(--g100); }
.ws-sidebar-expand .ph   { font-size: 14px; }
body[data-left-collapsed="1"]  .ws-sidebar-expand[data-side="left"]  { display: inline-flex; }
body[data-right-collapsed="1"] .ws-sidebar-expand[data-side="right"] { display: inline-flex; }

/* Touch-friendly hit sizes for sidebar chrome. */
@media (pointer: coarse) {
    .ws-sidebar-expand   { width: 44px; height: 44px; }
    .ws-sidebar-collapse { width: 44px; height: 40px; }
    .ws-sidebar-collapse .ph,
    .ws-sidebar-expand   .ph { font-size: 16px; }
}

/* Touch-only modifier keys, hosted inside the bottom tool dock alongside the
   tool buttons (separated by .ws-dock-mod-divider). Hidden by default and
   only revealed on coarse pointers. */
.ws-mod-bar {
    display: none;
    align-items: center;
    gap: 4px;
}
.ws-dock-mod-divider { display: none; }
@media (pointer: coarse) {
    .ws-mod-bar { display: inline-flex; }
}
/* (Sized overrides for .ws-dock-mod-divider live AFTER .ws-dock-divider so
   they actually win on source order — see end of dock-divider block.) */
.ws-mod-btn {
    min-width: 56px;
    height: 38px;
    padding: 0 10px;
    border: none;
    background: var(--bg-panel);
    color: var(--g700);
    font-family: var(--ff-body);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.06em;
    cursor: pointer;
    transition: background 0.12s, color 0.12s;
}
.ws-mod-btn:hover { background: var(--g100); color: var(--fg-default); }
.ws-mod-btn.active {
    background: var(--accent);
    color: var(--emphasis-fg);
}

.ws-tabs {
    display: flex;
    border-bottom: var(--border);
    background: var(--g50);
    flex-shrink: 0;
}

.ws-tab {
    flex: 1;
    /* Hard-pin every sidebar header to 40px so glyphs / layers / project /
       guides all align horizontally. Use flex centring instead of vertical
       padding so the height stays exact regardless of font metrics. */
    height: 40px;
    box-sizing: border-box;
    padding: 0 12px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: none;
    border-right: var(--border);
    font-family: var(--ff-body);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.1em;
    color: var(--g500);
    cursor: pointer;
    text-align: center;
    transition:
        background 0.1s,
        color 0.1s;
    user-select: none;
    /* Inactive tabs keep a 2px bottom border, greyed out so the rhythm
       matches the active tab's underline. */
    box-shadow: inset 0 -2px 0 0 var(--g300);
}
.ws-tab:last-child {
    border-right: none;
}
.ws-tab:hover {
    color: var(--fg-default);
}
.ws-tab.active {
    color: var(--fg-default);
    background: var(--bg-panel);
    box-shadow: inset 0 -2px 0 0 var(--emphasis-bg);
}

/* Active tab that hosts an inline action (e.g. + ADD inside GLYPHS) */
.ws-tab-with-action {
  justify-content: flex-start;
  gap: 8px;
  text-align: left;
  cursor: default;
}
.ws-tab-action {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  padding: 0;
  background: var(--g100);
  border: var(--border);
  color: var(--g600);
  cursor: pointer;
  transition: background 0.1s, color 0.1s, border-color 0.1s;
}
.ws-tab-action:hover  { background: var(--emphasis-bg); border-color: var(--fg-default); color: var(--emphasis-fg); }
.ws-tab-action:active { opacity: 0.82; }
.ws-tab-action .ph { font-size: 12px; }

.ws-panel {
    flex: 1;
    overflow-y: auto;
    padding: 14px 12px;
}
.ws-panel[hidden] {
    display: none;
}

.ws-empty {
    padding: 36px 12px;
    text-align: center;
    font-family: var(--ff-body);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.12em;
    color: var(--g400);
}

.ws-canvas {
    flex: 1;
    position: relative;
    overflow: hidden;
    background-color: var(--bg-workspace);
    min-width: 0;
    touch-action: none;
}
body[data-tool="select"] .ws-canvas {
    cursor: default;
}
.ws-canvas.is-panning {
    cursor: grabbing !important;
}

.ws-placeholder {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 32px;
    gap: 10px;
}
.ws-placeholder[hidden] {
    display: none !important;
}
.ws-placeholder svg {
    margin-bottom: 10px;
}

.ws-placeholder-title {
    font-family: var(--ff-display);
    font-size: 14px;
    color: var(--g400);
    letter-spacing: 0.12em;
}
.ws-placeholder-sub {
    font-size: 11px;
    color: var(--g400);
    letter-spacing: 0.04em;
    max-width: 280px;
    line-height: 1.7;
}

/* ─── Tool Dock ─────────────────────────────────────────── */
.ws-dock {
    position: absolute;
    bottom: 22px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 50;
    /* Cap width to the viewport so the dock can wrap on narrow screens
       instead of overflowing horizontally. */
    max-width: calc(100vw - 16px);
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    gap: 4px;
    padding: 5px;
    background: var(--bg-panel);
    border: var(--border-dark);
    box-shadow: 4px 4px 0 rgba(0, 0, 0, 0.15);
}
/* Tools group: doesn't wrap internally, so the whole block moves together
   when the mod bar drops to the next row. */
.ws-dock-group {
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    gap: 2px;
}

.ws-tool {
    width: 36px;
    height: 36px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-panel);
    border: 1px solid transparent;
    color: var(--g700);
    cursor: pointer;
    transition:
        background 0.08s,
        color 0.08s;
}
.ws-tool:hover {
    background: var(--g100);
    color: var(--fg-default);
}
.ws-tool:active {
    opacity: 0.82;
}
.ws-tool.active {
    background: var(--emphasis-bg);
    color: var(--emphasis-fg);
}
.ws-tool[disabled],
.ws-tool:disabled {
    opacity: 0.35;
    cursor: not-allowed;
    pointer-events: none;
}

.ws-dock-divider {
    width: 1px;
    height: 22px;
    background: var(--g200);
    margin: 0 4px;
}

/* Mod divider — full-width horizontal rule that forces the modifier bar to
   wrap to its own row on narrow coarse-pointer screens. Placed AFTER
   .ws-dock-divider so the height override actually wins. */
@media (pointer: coarse) {
    .ws-dock-mod-divider {
        display: block;
        flex-basis: 100%;
        width: 100%;
        height: 1px;
        margin: 4px 0;
    }
}
@media (pointer: coarse) and (min-width: 720px) {
    /* Wide enough to fit on one row — restore the original vertical look. */
    .ws-dock-mod-divider {
        flex-basis: auto;
        width: 1px;
        height: 22px;
        margin: 0 4px;
    }
}

/* ─── Glyph List (sidebar) ──────────────────────────────── */
.ws-glyphs-section {
    display: flex;
    flex-direction: column;
    flex: 0 1 260px;
    min-height: 100px;
    border-bottom: var(--border);
}

.ws-section-header { display: none; } /* legacy */

.ws-tabs-with-action {
  display: flex;
  align-items: stretch;
  border-bottom: var(--border);
  background: var(--g50);
}
.ws-tabs-with-action .ws-tab {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 8px;
  /* Match active-tab style from the right sidebar */
}
.ws-tab-count {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--g400);
}
.ws-tab.active .ws-tab-count { color: var(--g600); }

.ws-tabs-action {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 0 12px;
  background: transparent;
  border: none;
  border-left: var(--border);
  font-family: var(--ff-body);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--g500);
  cursor: pointer;
  user-select: none;
}
.ws-tabs-action:hover  { color: var(--fg-default); background: var(--g100); }
.ws-tabs-action:active { opacity: 0.82; }
.ws-tabs-action .ph    { font-size: 13px; }

.ws-glyphs-grid {
    flex: 1;
    overflow-y: auto;
    padding: 8px;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(30px, 1fr));
    gap: 2px;
    align-content: start;
}

.glyph-cell {
    aspect-ratio: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-panel);
    border: var(--border);
    font-family: var(--ff-body);
    font-size: 14px;
    color: var(--g700);
    cursor: pointer;
    user-select: none;
    transition:
        background 0.08s,
        border-color 0.08s,
        color 0.08s;
    position: relative;
}
.glyph-cell.empty {
    color: var(--g400);
}
.glyph-cell.system {
    background: var(--g50);
}
.glyph-cell:hover {
    border-color: var(--g500);
    color: var(--fg-default);
}
.glyph-cell.active {
    background: var(--emphasis-bg);
    border-color: var(--fg-default);
    color: var(--emphasis-fg);
}
.glyph-cell.active.system {
    background: var(--emphasis-bg);
}
.glyph-cell.done::after {
    content: "";
    position: absolute;
    bottom: 2px;
    right: 2px;
    width: 4px;
    height: 4px;
    background: var(--emphasis-bg);
}
.glyph-cell.active.done::after {
    background: var(--bg-panel);
}

/* ─── Glyph Frame (canvas) ──────────────────────────────── */
/* Edge-to-edge workspace SVG. Fills the entire ws-canvas; the glyphspace
   bounds are drawn as an inner rect, the surrounding area is "workspace". */
.glyph-frame {
    position: absolute;
    inset: 0;
    width:  100%;
    height: 100%;
    display: block;
    pointer-events: all;
    /* Without these, Chrome can start a text-selection gesture on pointerdown
       (especially on a fresh page state) which steals the drag — pointermove
       then fires on the document instead of the SVG and our preview goes
       stale. Hard-disable both selection and native touch gestures here. */
    user-select: none;
    -webkit-user-select: none;
    touch-action: none;
}
.glyph-frame[hidden] {
    display: none;
}

/* Full-SVG pointer catcher (canvas-pixel space). Transparent but paint-bearing
   so visiblePainted hit-testing fires across the whole workspace. */
.frame-bg {
    fill: rgba(255, 255, 255, 0.001);
    pointer-events: all;
}

/* Glyphspace background rect (font-coord space, inside #ws-view).
   White against the off-white workspace makes the cell read clearly without
   needing a border. */
.frame-glyphspace-bg {
    fill: var(--bg-glyphspace);
    pointer-events: none;
}

.frame-marquee {
    fill: rgba(234, 88, 12, 0.08);
    stroke: var(--accent);
    stroke-width: 1;
    /* Default to "touching" semantics — dashed outline matches AutoCAD/Figma. */
    stroke-dasharray: 4 3;
    vector-effect: non-scaling-stroke;
    pointer-events: none;
}
/* Left-to-right marquee = enclosed mode: solid outline so the user can
   distinguish at a glance which selection rule is active. */
.frame-marquee[data-containment="enclosed"] {
    stroke-dasharray: none;
}
.frame-marquee[hidden] {
    display: none;
}

.ws-zoom-indicator {
    position: absolute;
    bottom: 14px;
    left: 14px;
    background: var(--bg-panel);
    border: var(--border);
    padding: 4px 8px;
    font-family: var(--ff-body);
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.1em;
    color: var(--g500);
    cursor: pointer;
    user-select: none;
    z-index: 5;
    transition: background 0.12s, color 0.12s;
}
.ws-zoom-indicator:hover { background: var(--g100); color: var(--fg-default); }
.ws-zoom-indicator[hidden] { display: none; }

/* Glyphspace structural lines — ascender / baseline / descender extend
   horizontally across the entire workspace; x=0 and x=advanceWidth extend
   vertically. They mark the glyph cell visually without a border. */
.frame-glyphline {
    fill: none;
    stroke-width: 1;
    vector-effect: non-scaling-stroke;
    pointer-events: none;
}
.glyphline-baseline  { stroke: var(--glyphline); }
.glyphline-ascender  { stroke: var(--glyphline); }
.glyphline-descender { stroke: var(--glyphline); }
.glyphline-left      { stroke: var(--glyphline); }
.glyphline-right     { stroke: var(--glyphline); }

/* Wide invisible hit zone over each glyphline. Rendered only while the guide
   tool is active (see renderGlyphlines). Hover styles the SAME element with
   an accent stroke so it visually replaces the dark glyphline beneath it. */
.frame-glyphline-hit {
    /* Constant stroke-width — with pointer-events:stroke, the hit area equals
       the rendered stroke. If hover changed the width, the hit zone would
       shrink under the cursor and the drag-start could land in dead space
       between the new and old extents. */
    stroke: var(--accent);
    stroke-opacity: 0;
    stroke-width: 10;
    vector-effect: non-scaling-stroke;
    fill: none;
    pointer-events: stroke;
}
.frame-glyphline-hit[data-kind="h"] { cursor: ns-resize; }
.frame-glyphline-hit[data-kind="v"] { cursor: ew-resize; }
/* Hover affordance is gated to the guide tool so a stale hit element from
   a prior render can't flash accent after the user switches tools. */
body[data-tool="guide"] .frame-glyphline-hit:hover {
    stroke-opacity: 0.35;
}
/* Touch: widen hit zones so a fingertip can actually grab a glyphline. */
@media (pointer: coarse) {
    .frame-glyphline-hit,
    .frame-guide-hit { stroke-width: 28; }
}

/* Preview line shown while dragging a glyphline to spawn a guide OR moving
   an existing guide. */
.frame-guide.guide-preview {
    stroke: var(--accent);
    stroke-width: 1.25;
    stroke-dasharray: 4 3;
    opacity: 0.9;
}

/* Wide hit zone over each existing guide. Rendered only while the guide
   tool is active. Stroke-width is held constant so the hit area never
   shrinks out from under the cursor — only stroke-opacity changes on hover. */
.frame-guide-hit {
    stroke: var(--accent);
    stroke-opacity: 0;
    stroke-width: 10;
    vector-effect: non-scaling-stroke;
    fill: none;
    pointer-events: stroke;
}
.frame-guide-hit[data-kind="h"] { cursor: ns-resize; }
.frame-guide-hit[data-kind="v"] { cursor: ew-resize; }
body[data-tool="guide"] .frame-guide-hit:hover {
    stroke-opacity: 0.35;
}

/* User grid (lined or dotted). Renders ON TOP of contours so the user can
   always see the underlying grid while drawing. */
.frame-grid-line {
    stroke: var(--grid-color, #737373);
    stroke-opacity: var(--grid-opacity, 0.3);
    stroke-width: 1;
    vector-effect: non-scaling-stroke;
    fill: none;
    pointer-events: none;
    /* Difference blend keeps mid-gray grid lines readable on any background
       (white glyphspace, dark glyphspace, glyph fills). With #737373 as the
       default, the result lands near #d9 on white and ~#36 on dark — soft
       in both themes without per-theme tuning. */
    mix-blend-mode: difference;
}
.frame-grid-dot {
    fill: var(--grid-color, #737373);
    fill-opacity: var(--grid-opacity, 0.3);
    pointer-events: none;
    mix-blend-mode: difference;
}

/* Segmented two-button toggle used by GRID STYLE and similar binary picks. */
.segmented {
    display: flex;
    border: var(--border);
}
.seg-btn {
    flex: 1;
    padding: 7px 0;
    background: var(--bg-panel);
    color: var(--g600);
    border: none;
    border-right: var(--border);
    font-family: var(--ff-body);
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.1em;
    cursor: pointer;
}
.seg-btn:last-child { border-right: none; }
.seg-btn:hover { color: var(--fg-default); background: var(--g50); }
.seg-btn.active {
    background: var(--emphasis-bg);
    color: var(--emphasis-fg);
}

/* Project-global guides. Stroke colour is set inline per-guide so the user
   can override per-group later — this rule only owns weight and behaviour. */
.frame-guide {
    stroke-width: 1;
    vector-effect: non-scaling-stroke;
    fill: none;
    pointer-events: none;
}

/* Guide tool cursor — crosshair makes the placement target obvious. */
body[data-tool="guide"] #glyph-frame {
    cursor: crosshair;
}

/* ─── Glyph paths ───────────────────────────────────────── */
/* Visual fill — one combined path per glyph, evenodd makes inner contours
   become holes when they sit inside outer contours. */
.glyph-path-fill {
    fill: var(--fg-glyph);
    fill-rule: evenodd;
    stroke: none;
}
/* Per-contour invisible hit targets — they catch clicks / right-clicks and
   carry the orange selected stroke. */
.glyph-path-hit {
    fill: transparent;
    fill-rule: evenodd;
    stroke: none;
    pointer-events: painted;
    cursor: default;
}
body[data-tool="select"] .glyph-path-hit {
    cursor: pointer;
}
/* (Hover + selected outlines are rendered into #frame-overlay-outlines so
   they stay on top of grid / guides. The hit path stays paint-only.) */
/* Drawing tools keep their crosshair even when the cursor crosses an existing
   contour's hit area — without this, .glyph-path-hit's default cursor wins. */
body[data-tool="pen"]    .glyph-path-hit,
body[data-tool="rect"]   .glyph-path-hit,
body[data-tool="circle"] .glyph-path-hit,
body[data-tool="guide"]  .glyph-path-hit {
    cursor: inherit;
}
.glyph-path-hit.selected {
    fill: rgba(234, 88, 12, 0.05);  /* faint accent fill so the selected layer reads on top of holes */
}

/* Outline overlays — rendered into #frame-overlay-outlines which sits above
   the user grid and the guides layer, so neither obscures shape outlines.
   Strokes are thicker than the previous in-contour-layer styles so they
   read clearly against translucent overlays beneath. */
.glyph-path-overlay {
    fill: none;
    stroke-linejoin: miter;
    stroke-miterlimit: 10;
    vector-effect: non-scaling-stroke;
    pointer-events: none;
}
.overlay-hover    { stroke: var(--hover);  stroke-width: 2.25; }
.overlay-selected { stroke: var(--accent); stroke-width: 2.25; }

.glyph-path-progress {
    fill: none;
    stroke: var(--hover);
    stroke-width: 2.25;
    stroke-linejoin: miter;
    stroke-miterlimit: 10;
    vector-effect: non-scaling-stroke;
    /* The in-progress pen contour is rendered in #frame-pen-preview which
       sits above the contour fills in DOM order; this rule just guarantees
       it never gets visually swallowed by a black fill. */
    pointer-events: none;
}
.pen-close-preview {
    fill: none;
    stroke: var(--hover);
    stroke-width: 1.5;
    vector-effect: non-scaling-stroke;
    pointer-events: none;
}

/* Pen rubber-band: the cubic the next click would commit. Solid indigo so
   it reads as a live preview of the curve, matching the in-progress path. */
.pen-preview-curve {
    fill: none;
    stroke: var(--hover);
    stroke-width: 1.5;
    vector-effect: non-scaling-stroke;
    pointer-events: none;
}

/* Paper-mode bounding box + transform handles. */
.paper-bbox {
    fill: none;
    stroke: var(--accent);
    stroke-width: 1.25;
    vector-effect: non-scaling-stroke;
    pointer-events: none;
}
.paper-handle {
    fill: var(--white);
    stroke: var(--accent);
    stroke-width: 1.25;
    vector-effect: non-scaling-stroke;
    cursor: pointer;
}
.paper-handle[data-handle-role="n"],  .paper-handle[data-handle-role="s"]  { cursor: ns-resize; }
.paper-handle[data-handle-role="e"],  .paper-handle[data-handle-role="w"]  { cursor: ew-resize; }
.paper-handle[data-handle-role="nw"], .paper-handle[data-handle-role="se"] { cursor: nwse-resize; }
.paper-handle[data-handle-role="ne"], .paper-handle[data-handle-role="sw"] { cursor: nesw-resize; }
.paper-handle[data-handle-role="rotate"] { cursor: grab; }
.paper-handle[data-handle-role="rotate"]:active { cursor: grabbing; }
.paper-rotate-stem {
    stroke: var(--accent);
    stroke-width: 1.25;
    vector-effect: non-scaling-stroke;
    pointer-events: none;
}

/* Shape-mode segment-insertion indicator — appears at the foot of the
   perpendicular projection from the cursor onto a contour edge. Click adds
   a new anchor at that location. */
.segment-insert-dot {
    fill: var(--accent);
    stroke: var(--white);
    stroke-width: 1.5;
    vector-effect: non-scaling-stroke;
    cursor: copy;
    pointer-events: all;
}

/* anchors */
.pen-anchor {
    fill: var(--white);
    stroke: var(--accent);
    stroke-width: 1.25;
    vector-effect: non-scaling-stroke;
}
.pen-anchor[data-role="anchor"] {
    cursor: move;
}
.pen-anchor.selected {
    fill: var(--accent);
    stroke: var(--accent);
}
.pen-anchor-first {
    fill: var(--accent);
    stroke: var(--accent);
}
.pen-anchor-first.close-target {
    fill: var(--white);
    stroke: var(--accent);
    stroke-width: 2;
}

/* handles */
.pen-handle-line {
    stroke: var(--accent);
    stroke-width: 1;
    stroke-dasharray: 2 2;
    vector-effect: non-scaling-stroke;
    pointer-events: none;
    opacity: 0.7;
}
.pen-handle {
    fill: var(--white);
    stroke: var(--accent);
    stroke-width: 1;
    vector-effect: non-scaling-stroke;
}
.pen-handle[data-role="handle"] {
    cursor: move;
}
.pen-handle.selected {
    fill: var(--accent);
    stroke: var(--accent-strong);
}

.pen-snap-target {
  fill: none;
  stroke: var(--accent);
  stroke-width: 1.2;
  stroke-dasharray: 2 1.5;
  vector-effect: non-scaling-stroke;
  pointer-events: none;
}

/* canvas cursor per active tool */
body[data-tool="pen"] .ws-canvas,
body[data-tool="rect"] .ws-canvas,
body[data-tool="circle"] .ws-canvas {
    cursor: crosshair;
}
body[data-tool="hand"] .ws-canvas,
body[data-temp-tool="hand"] .ws-canvas { cursor: grab; }
body[data-tool="hand"] .ws-canvas.is-panning,
body[data-temp-tool="hand"] .ws-canvas.is-panning { cursor: grabbing !important; }

/* Tool button shortcut hint chip */
.ws-tool { position: relative; }
.ws-tool-hint {
  position: absolute;
  bottom: 2px;
  right: 3px;
  font-family: var(--ff-body);
  font-size: 8px;
  font-weight: 700;
  letter-spacing: 0;
  color: var(--g400);
  background: transparent;
  border: none;
  padding: 0;
  pointer-events: none;
  user-select: none;
}
.ws-tool:hover .ws-tool-hint { color: var(--g600); }
.ws-tool.active .ws-tool-hint { color: rgba(255, 255, 255, 0.55); }

/* ─── Layers Panel ──────────────────────────────────────── */
.layer-item {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px 8px;
    border: var(--border);
    background: var(--bg-panel);
    margin-bottom: 4px;
    cursor: pointer;
    user-select: none;
    transition:
        background 0.08s,
        border-color 0.08s;
}
.layer-item:hover {
    border-color: var(--g500);
}
.layer-item.selected {
    background: var(--emphasis-bg);
    border-color: var(--fg-default);
    color: var(--emphasis-fg);
}
.layer-item.hidden-layer .layer-name {
    color: var(--g400);
    text-decoration: line-through;
}
.layer-item.selected.hidden-layer .layer-name {
    color: var(--g400);
}
/* Hole row: subordinate to its parent — indent + dim and tag visually. */
.layer-item.layer-hole {
    padding-left: 18px;
}
.layer-item.layer-hole .layer-name {
    color: var(--g600);
}
.layer-item.layer-hole.selected .layer-name {
    color: var(--emphasis-fg);
}
.layer-tag {
    flex-shrink: 0;
    font-family: var(--ff-body);
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.1em;
    padding: 1px 5px;
    border: var(--border-mid);
    color: var(--g500);
    background: var(--bg-panel);
}
.layer-item.selected .layer-tag {
    border-color: rgba(255, 255, 255, 0.35);
    color: rgba(255, 255, 255, 0.85);
    background: transparent;
}

.layer-name {
    flex: 1;
    font-family: var(--ff-body);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.06em;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.layer-btn {
    width: 22px;
    height: 22px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: none;
    color: var(--g500);
    cursor: pointer;
    transition:
        color 0.1s,
        background 0.1s;
    flex-shrink: 0;
}
.layer-btn:hover {
    color: var(--fg-default);
    background: var(--g100);
}
.layer-item.selected .layer-btn {
    color: var(--g400);
}
.layer-item.selected .layer-btn:hover {
    color: var(--emphasis-fg);
    background: rgba(255, 255, 255, 0.12);
}

.layer-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  cursor: text;
}
.layer-name.editing {
  outline: 1px solid var(--accent);
  background: var(--bg-panel);
  color: var(--fg-default);
  padding: 1px 4px;
  margin: -1px -4px;
  cursor: text;
  text-overflow: clip;
}
.layer-item.selected .layer-name.editing { /* keep white bg readable */
  outline-color: var(--accent);
}

/* ─── Guides Panel ──────────────────────────────────────── */
.guide-group {
    border: var(--border);
    background: var(--bg-panel);
    margin-bottom: 6px;
}
.guide-group.active {
    border-color: var(--accent);
    box-shadow: inset 2px 0 0 0 var(--accent);
}
.guide-group.hidden-group .guide-group-header { opacity: 0.55; }

.guide-group-header {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px 8px;
    border-bottom: var(--border);
    cursor: pointer;
    user-select: none;
}
.guide-group-vis,
.guide-group-btn {
    width: 22px;
    height: 22px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: none;
    color: var(--g500);
    cursor: pointer;
    transition: color 0.1s, background 0.1s;
    flex-shrink: 0;
}
.guide-group-vis:hover,
.guide-group-btn:hover:not([disabled]) {
    color: var(--fg-default);
    background: var(--g100);
}
.guide-group-btn[disabled] {
    opacity: 0.3;
    cursor: not-allowed;
}

.guide-color-swatch {
    display: inline-block;
    width: 16px;
    height: 16px;
    border: var(--border-mid);
    cursor: pointer;
    flex-shrink: 0;
    padding: 0;
}

.guide-group-name {
    flex: 1;
    min-width: 0;
    font-family: var(--ff-body);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.08em;
    color: var(--fg-default);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    cursor: text;
}
.guide-group-name.editing {
    outline: 1px solid var(--accent);
    background: var(--bg-panel);
    padding: 1px 4px;
    margin: -1px -4px;
    text-overflow: clip;
}
.guide-group-count {
    font-family: var(--ff-body);
    font-size: 10px;
    font-weight: 600;
    color: var(--g500);
    padding: 1px 5px;
    border: var(--border);
    background: var(--g50);
    flex-shrink: 0;
}

.guide-group-body {
    padding: 4px 8px 6px;
}
.guide-empty {
    font-family: var(--ff-body);
    font-size: 10px;
    color: var(--g400);
    letter-spacing: 0.08em;
    padding: 4px 0;
    text-align: center;
}

.guide-row {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 3px 0;
}
.guide-row.is-hidden { opacity: 0.45; }
.guide-orient {
    width: 18px;
    height: 18px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-family: var(--ff-body);
    font-size: 10px;
    font-weight: 700;
    color: var(--emphasis-fg);
    background: var(--g700);
    flex-shrink: 0;
}
.guide-orient[data-orientation="v"] { background: var(--g500); }
.guide-anchor {
    flex: 1.2;
    min-width: 0;
    height: 24px;
    padding: 0 4px;
    border: var(--border);
    background: var(--bg-panel);
    font-family: var(--ff-body);
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.04em;
    color: var(--fg-default);
    cursor: pointer;
}
.guide-anchor:focus {
    outline: 1px solid var(--accent);
    outline-offset: -1px;
    border-color: var(--accent);
}
.guide-pos {
    flex: 1;
    min-width: 0;
    height: 24px;
    padding: 0 6px;
    border: var(--border);
    background: var(--bg-panel);
    font-family: var(--ff-body);
    font-size: 11px;
    color: var(--fg-default);
}
.guide-pos:focus {
    outline: 1px solid var(--accent);
    outline-offset: -1px;
    border-color: var(--accent);
}
.guide-btn {
    width: 22px;
    height: 22px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: none;
    color: var(--g500);
    cursor: pointer;
    flex-shrink: 0;
}
.guide-btn:hover { color: var(--fg-default); background: var(--g100); }

.glyph-frame-label {
    position: absolute;
    top: 14px;
    right: 14px;
    font-family: var(--ff-body);
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.1em;
    color: var(--g500);
    background: var(--bg-panel);
    border: var(--border);
    padding: 4px 8px;
    pointer-events: none;
}
/* Make room for the right-sidebar uncollapse button when collapsed. */
body[data-right-collapsed="1"] .glyph-frame-label { right: 56px; }
@media (pointer: coarse) {
    body[data-right-collapsed="1"] .glyph-frame-label { right: 64px; }
}
.glyph-frame-label[hidden] {
    display: none;
}

/* ─── Glyph Properties Panel ────────────────────────────── */
.glyph-char-preview {
    font-family: var(--ff-body);
    font-size: 32px;
    background: var(--g50);
    border: var(--border-mid);
    padding: 24px 12px;
    text-align: center;
    letter-spacing: 0;
    margin-bottom: 14px;
    background-image: var(--btn-grid-dark);
    background-size: 8px 8px;
}

.field-readonly {
    font-family: var(--ff-body);
    font-size: 12px;
    padding: 8px 10px;
    background: var(--g50);
    border: var(--border-mid);
    color: var(--g700);
    user-select: text;
}

.field-label-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}

.field-action {
    background: transparent;
    border: none;
    padding: 0;
    font-family: var(--ff-body);
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.1em;
    color: var(--g500);
    cursor: pointer;
    text-decoration: underline;
    text-underline-offset: 2px;
}
.field-action:hover {
    color: var(--fg-default);
}
.field-action[hidden] {
    display: none;
}

/* ─── Right Sidebar Properties Panel ────────────────────── */
.prop-section {
    padding: 12px;
}

.shortcut-list {
  display: flex;
  flex-direction: column;
  gap: 5px;
  font-family: var(--ff-body);
}
.shortcut-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 10px;
  color: var(--g600);
  letter-spacing: 0.04em;
}
.shortcut-row .kbd-group {
  display: inline-flex;
  gap: 3px;
}
.shortcut-row kbd {
  display: inline-block;
  min-width: 18px;
  padding: 1px 5px;
  text-align: center;
  font-family: var(--ff-body);
  font-size: 9px;
  font-weight: 700;
  background: var(--g100);
  border: var(--border-mid);
  color: var(--g700);
  line-height: 1.4;
  white-space: nowrap;
}
.prop-section-title {
    font-family: var(--ff-body);
    font-size: 12px;
    letter-spacing: 0.06em;
    color: var(--g500);
    text-transform: uppercase;
    margin-bottom: 8px;
    display: block;
}
.prop-section.collapsible .prop-section-title {
    margin-bottom: 0;
}
.prop-section-toggle {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    padding: 0;
    background: none;
    border: none;
    cursor: pointer;
    color: var(--g500);
}
.prop-section-toggle:hover {
    color: var(--fg-default);
}
.prop-section-toggle:active {
    opacity: 0.7;
}
.prop-section-toggle .chevron {
    color: var(--g500);
    transition: transform 120ms ease;
}
.prop-section.collapsible .prop-section-body {
    display: none;
    margin-top: 10px;
}
.prop-section.collapsible.open .prop-section-body {
    display: block;
}
.prop-section.collapsible.open .prop-section-toggle .chevron {
    transform: rotate(180deg);
}

.field-toggle {
    display: flex;
    align-items: center;
    gap: 8px;
    cursor: pointer;
    font-family: var(--ff-body);
    font-size: 12px;
    letter-spacing: 0.04em;
    color: var(--g700);
    text-transform: uppercase;
    user-select: none;
}
.field-toggle input[type="checkbox"] {
    appearance: none;
    -webkit-appearance: none;
    width: 14px;
    height: 14px;
    border: 1px solid var(--g400);
    background: var(--bg-input);
    cursor: pointer;
    position: relative;
    flex: 0 0 auto;
}
.field-toggle input[type="checkbox"]:checked {
    background: var(--fg-default);
    border-color: var(--fg-default);
}
.field-toggle input[type="checkbox"]:checked::after {
    content: "";
    position: absolute;
    left: 3px;
    top: 0px;
    width: 5px;
    height: 9px;
    border: solid var(--bg-input);
    border-width: 0 2px 2px 0;
    transform: rotate(40deg);
}

.field-grid-2 {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 8px;
    margin-bottom: 10px;
}
.field-grid-2 .field-group {
    margin-bottom: 0;
}
