/* Shared interface primitives. See docs/ui-style-guide.md before adding a variant.
   Layout utilities belong to callers; typography and control paint belong here. */
:root {
    --ui-font-sans: "IBM Plex Sans", ui-sans-serif, system-ui, sans-serif;
    --ui-font-mono: "JetBrains Mono", ui-monospace, monospace;
    --ui-font-brand: "IBM Plex Mono", ui-monospace, monospace;
    --ui-radius-control: 0.25rem;
    --ui-radius-panel: 0.25rem;
    --ui-radius-dialog: 0.25rem;
    --ui-control-height: 2.25rem;
    --ui-control-small: 1.75rem;
}

html { font-size: 100%; }
html body { font-family: var(--ui-font-sans); font-size: 0.875rem; line-height: 1.25rem; }
button, input, select, textarea { font-family: inherit; }
code, pre, kbd, samp { font-family: var(--ui-font-mono); }
.brand-logo { font-family: var(--ui-font-brand); }
.ui-accent { color: rgb(var(--c-brand-400)); }
/* Color only, for controls that own their geometry (steps, chat and checkboxes). */
html .ui-brand-fill { background-color: rgb(var(--c-brand-400)); color: rgb(var(--c-brand-100)); }
html .ui-brand-fill:is(button, a):hover:not(:disabled) { background-color: rgb(var(--c-brand-500)); }
html .ui-brand-fill:disabled { background-color: rgb(var(--c-zinc-800)); color: rgb(var(--c-zinc-500)); }

/* Explicit roles beat incidental utility ordering, without !important. Color
   is inherited so status headings and titles over artwork remain meaningful. */
html :is(.ui-title, .ui-page-title, .ui-dialog-title, .ui-card-title,
    .ui-card-title-compact, .ui-card-title-list, .ui-section-title, .ui-subsection-title, .ui-title-display) {
    font-weight: 600;
    letter-spacing: -0.015em;
    text-transform: none;
    overflow-wrap: anywhere;
}
html .ui-title { font-size: 1.5rem; line-height: 1.875rem; }
html .ui-page-title { font-size: 1.5rem; line-height: 2rem; }
html .ui-dialog-title { font-size: 1.25rem; line-height: 1.625rem; }
html .ui-card-title { font-size: 1.0625rem; line-height: 1.4375rem; }
html .ui-card-title-list { font-size: 1.25rem; line-height: 1.625rem; }
html .ui-section-title { font-size: 1rem; line-height: 1.375rem; }
html .ui-subsection-title { font-size: 0.875rem; line-height: 1.25rem; }
html .ui-card-title-compact { font-size: 0.875rem; line-height: 1.25rem; }
html .ui-title-display { font-size: 2rem; line-height: 2.375rem; }
html .ui-label { font-size: 0.75rem; line-height: 1.125rem; font-weight: 500; letter-spacing: normal; text-transform: none; }
html .ui-body { font-size: 0.875rem; line-height: 1.25rem; }
html .ui-meta { font-size: 0.75rem; line-height: 1.125rem; }
html .ui-caption { font-size: 0.6875rem; line-height: 1rem; }

.ui-panel, .ui-dialog {
    background: rgb(var(--c-zinc-900));
    border: 1px solid rgb(var(--c-zinc-800));
    border-radius: var(--ui-radius-panel);
}
.ui-dialog { border-color: rgb(var(--c-zinc-700)); border-radius: var(--ui-radius-dialog); box-shadow: 0 16px 48px rgb(0 0 0 / 0.2); }
.ui-panel-interactive { box-shadow: 0 1px 2px rgb(0 0 0 / 0.04); transition: border-color 120ms ease, box-shadow 120ms ease; }
.ui-panel-interactive:hover, .ui-panel-interactive:focus-within { border-color: rgb(var(--c-active-400) / 0.55); box-shadow: 0 3px 10px rgb(0 0 0 / 0.08); }
.ui-card-meta { border-top: 1px solid rgb(var(--c-zinc-800)); padding-top: 0.75rem; }
.ui-cover-badge { padding: 0.125rem 0.5rem; border: 1px solid rgb(var(--c-zinc-900) / 0.65); border-radius: 0.25rem; background: rgb(var(--c-zinc-900) / 0.92); color: rgb(var(--c-zinc-200)); font-weight: 500; }
.ui-list-card { border-radius: 0.25rem; }
/* List covers use ONE aspect ratio everywhere (card, flagship-wide, compact,
   profile) so the same artwork crops identically; fixed heights made the ratio
   vary with column width and produced inconsistent crops. */
html .ui-list-cover { height: auto; aspect-ratio: 2 / 1; }
html .ui-list-cover.is-wide { height: auto; aspect-ratio: 2 / 1; }
html .ui-list-cover.is-compact { height: auto; aspect-ratio: 2 / 1; }
.ui-list-card-body { padding: 1rem 1.125rem; }
.ui-list-card-body.is-compact { padding: 0.75rem; }

.ui-button, .ui-icon-button { display: inline-flex; }
html :is(.ui-button, .ui-icon-button) {
    align-items: center;
    justify-content: center;
    gap: 0.4375rem;
    min-height: var(--ui-control-height);
    padding: 0.4375rem 0.75rem;
    border: 1px solid rgb(var(--c-zinc-700));
    border-radius: var(--ui-radius-control);
    background: rgb(var(--c-zinc-900));
    color: rgb(var(--c-zinc-300));
    font-size: 0.875rem;
    line-height: 1.25rem;
    font-weight: 500;
    text-decoration: none;
    cursor: pointer;
    transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease;
}
html :is(.ui-button, .ui-icon-button):hover:not(:disabled) { background: rgb(var(--c-zinc-800) / 0.45); color: rgb(var(--c-zinc-100)); }
html .ui-button-primary { background: rgb(var(--c-action-600)); border-color: transparent; color: rgb(var(--c-action-100)); }
html .ui-button-primary:hover:not(:disabled) { background: rgb(var(--c-action-500)); color: rgb(var(--c-action-100)); }
html .ui-button-danger { background: rgb(var(--c-red-600)); border-color: transparent; color: white; }
html .ui-button-danger:hover:not(:disabled) { background: rgb(var(--c-danger-500)); color: white; }
html .ui-button-ghost { background: transparent; border-color: transparent; color: rgb(var(--c-zinc-400)); }
html .ui-button.is-active, html .ui-button.is-active:hover:not(:disabled) { background: rgb(var(--c-active-900)); color: rgb(var(--c-zinc-100)); border-color: rgb(var(--c-zinc-700)); }
html .ui-button-danger.ui-button-ghost { background: transparent; border-color: transparent; color: rgb(var(--c-red-400)); }
html .ui-button-danger.ui-button-ghost:hover:not(:disabled) { background: rgb(var(--c-red-900) / 0.3); color: rgb(var(--c-red-300)); }
html .ui-button-sm { min-height: var(--ui-control-small); padding: 0.25rem 0.625rem; font-size: 0.75rem; line-height: 1.125rem; }
html .ui-icon-button { min-width: var(--ui-control-small); min-height: var(--ui-control-small); padding: 0.25rem; }
html :is(.ui-button, .ui-icon-button):disabled { opacity: 0.45; cursor: not-allowed; }
html :is(.ui-button, .ui-icon-button) svg { flex-shrink: 0; }

html .ui-switch {
    display: inline-flex; align-items: center; justify-content: flex-end; gap: 0.5rem;
    min-height: var(--ui-control-height); padding: 0;
    border: 0; border-radius: var(--ui-radius-control);
    background: transparent; color: rgb(var(--c-zinc-400));
    font-size: 0.75rem; line-height: 1.125rem; cursor: pointer;
}
.ui-switch-track {
    position: relative; flex-shrink: 0; width: 2.25rem; height: 1.375rem;
    border: 1px solid rgb(var(--c-zinc-600)); border-radius: var(--ui-radius-control);
    background: rgb(var(--c-zinc-800)); transition: background-color 120ms ease;
}
.ui-switch-track::after {
    content: ''; position: absolute; top: 2px; left: 2px; width: 1rem; height: 1rem;
    border-radius: 0.1875rem; background: rgb(var(--c-zinc-400));
    transition: transform 120ms ease, background-color 120ms ease;
}
.ui-switch[aria-checked="true"] .ui-switch-track { background: rgb(var(--c-brand-400)); border-color: rgb(var(--c-brand-400)); }
.ui-switch[aria-checked="true"] .ui-switch-track::after { transform: translateX(0.875rem); background: rgb(var(--c-brand-100)); }
html .ui-switch:hover:not(:disabled, [aria-disabled="true"]) { color: rgb(var(--c-zinc-100)); }
.ui-switch:hover:not(:disabled, [aria-disabled="true"]) .ui-switch-track { border-color: rgb(var(--c-zinc-400)); }
html .ui-switch:is(:disabled, [aria-disabled="true"]) { opacity: 0.45; cursor: not-allowed; }
/* Inverted-semantics toggle: ON is the calm/expected state (grey) and OFF is the
   one worth flagging (muted red, not bright). Used by Auto-generate ideas, where
   a climb NOT generating is the state to notice. Scoped via .ui-switch-flag-off
   so normal toggles keep the brand-on styling. */
html .ui-switch-flag-off .ui-switch-track { background: rgb(var(--c-red-900)); border-color: rgb(var(--c-red-700)); }
html .ui-switch-flag-off .ui-switch-track::after { background: rgb(var(--c-red-400)); }
html .ui-switch-flag-off[aria-checked="true"] .ui-switch-track { background: rgb(var(--c-zinc-700)); border-color: rgb(var(--c-zinc-500)); }
html .ui-switch-flag-off[aria-checked="true"] .ui-switch-track::after { background: rgb(var(--c-zinc-200)); }
html .ui-switch-flag-off:hover:not(:disabled, [aria-disabled="true"]) .ui-switch-track { border-color: rgb(var(--c-red-500)); }
html .ui-switch-flag-off[aria-checked="true"]:hover:not(:disabled, [aria-disabled="true"]) .ui-switch-track { border-color: rgb(var(--c-zinc-400)); }

html .ui-field {
    min-height: var(--ui-control-height);
    padding: 0.4375rem 0.75rem;
    border: 1px solid rgb(var(--c-zinc-700));
    border-radius: var(--ui-radius-control);
    background-color: rgb(var(--c-zinc-900));
    color: rgb(var(--c-zinc-100));
    font-size: 0.875rem;
    line-height: 1.25rem;
}
html .ui-field::placeholder { color: rgb(var(--c-zinc-500)); opacity: 1; }
html .ui-field:disabled { opacity: 0.6; cursor: not-allowed; }
html .ui-field:read-only { color: rgb(var(--c-zinc-300)); }
html .ui-field:is(.is-invalid, [aria-invalid="true"]) { border-color: rgb(var(--c-red-500)); }
html textarea.ui-field { height: auto; }
html :is(.ui-field-search, .ui-field-leading) { padding-left: 2.125rem; }
html select.ui-field.app-select { padding-right: 2.25rem; }
html :is(.ui-button, .ui-icon-button, .ui-switch, .ui-field, .ui-filter, .ui-tab):focus-visible {
    outline: 2px solid rgb(var(--c-emerald-400));
    outline-offset: 2px;
    box-shadow: none;
}

html .ui-filter {
    display: inline-flex; align-items: center; justify-content: center; gap: 0.375rem;
    min-height: var(--ui-control-small); padding: 0.1875rem 0.625rem;
    border: 1px solid transparent; border-radius: var(--ui-radius-control);
    background: transparent; color: rgb(var(--c-zinc-400));
    font-size: 0.75rem; line-height: 1.25rem; font-weight: 400;
    cursor: pointer; transition: background-color 120ms ease, color 120ms ease;
}
html .ui-filter:hover { background: rgb(var(--c-zinc-800) / 0.45); color: rgb(var(--c-zinc-100)); }
html .ui-filter:is(.is-active, [aria-pressed="true"], [aria-current="true"]) { background: rgb(var(--c-active-900)); color: rgb(var(--c-zinc-100)); }
html .ui-filter svg { width: 0.875rem; height: 0.875rem; }
html .ui-tab {
    display: inline-flex; align-items: center; gap: 0.4375rem;
    min-height: 3rem; padding: 0.75rem 0.25rem; margin-bottom: -1px;
    border: 0; border-bottom: 2px solid transparent;
    background: transparent; color: rgb(var(--c-zinc-400));
    font-size: 0.875rem; line-height: 1.25rem; font-weight: 500;
}
html .ui-tab:hover { color: rgb(var(--c-zinc-100)); }
html .ui-tab:is(.is-active, [aria-current="page"], [aria-selected="true"]) { border-bottom-color: rgb(var(--c-active-400)); color: rgb(var(--c-zinc-100)); }

.ui-page-header { min-height: 4.75rem; padding: 0.75rem 1.75rem; background: rgb(var(--c-header-900)); }
.ui-breadcrumb { font-size: 0.875rem; line-height: 1.25rem; }
.ui-breadcrumb > :is(a, span):last-child { color: rgb(var(--c-zinc-100)); font-weight: 500; }
.ui-sidebar { width: 13rem; background: rgb(var(--c-sidebar-900)); }
.ui-sidebar-brand { min-height: 4.75rem; border-bottom: 1px solid rgb(var(--c-zinc-800)); }
.ui-sidebar-link { display: flex; align-items: center; gap: 0.625rem; min-height: 2.25rem; padding: 0.5rem 0.625rem; border-radius: var(--ui-radius-control); color: rgb(var(--c-zinc-400)); font-size: 0.875rem; line-height: 1.25rem; font-weight: 400; }
.ui-sidebar-link:hover { background: rgb(var(--c-zinc-800) / 0.4); color: rgb(var(--c-zinc-100)); }
.ui-sidebar-link.is-active { background: rgb(var(--c-active-900)); color: rgb(var(--c-zinc-100)); font-weight: 500; box-shadow: inset 2px 0 rgb(var(--c-active-400)); }
.ui-sidebar-sub { font-size: 0.8125rem; line-height: 1.25rem; }
.ui-sidebar-search { min-height: 2.125rem; }
.ui-star { display: inline-flex; align-items: center; gap: 0.3125rem; min-height: 1.75rem; padding: 0.25rem; border-radius: var(--ui-radius-control); font-size: 0.75rem; line-height: 1.125rem; color: rgb(var(--c-zinc-500)); }
.ui-star:hover { background: rgb(var(--c-zinc-800) / 0.45); }
html .ui-star[aria-pressed="true"], html .ui-star[aria-pressed="true"]:hover { color: rgb(var(--c-amber-400)); }
html .ui-star-cover { padding: 0.125rem 0.5rem; border: 1px solid rgb(var(--c-zinc-900) / 0.65); border-radius: 0.25rem; background: rgb(var(--c-zinc-900) / 0.92); color: rgb(var(--c-zinc-300)); }
html .ui-star-cover:hover { background: rgb(var(--c-zinc-900)); }
html .ui-star-cover[aria-pressed="true"], html .ui-star-cover[aria-pressed="true"]:hover { color: rgb(var(--c-amber-400)); }

@media (max-width: 639px) {
    .ui-page-header { padding: 0.875rem 1rem; }
    html .ui-card-title-list { font-size: 1.125rem; line-height: 1.5rem; }
    .ui-list-card-body { padding: 1rem 0.875rem; }
    html .ui-title-display { font-size: 1.5rem; line-height: 1.875rem; }
    .ui-hub-toolbar { flex-wrap: wrap; }
    .ui-hub-search { flex-basis: 100%; }
    .ui-hub-toolbar select { width: 100%; }
}
@media (pointer: coarse) {
    html :is(.ui-button, .ui-icon-button, .ui-switch, .ui-field, .ui-filter, .ui-star, .ui-sidebar-link, .ui-sidebar-search, .ui-menu-toggle) { min-height: 44px; }
    html :is(.ui-icon-button, .ui-star, .ui-menu-toggle) { min-width: 44px; }
    html :is(input, textarea, select):not([type="checkbox"], [type="radio"]) { font-size: 1rem; }
}
@media (prefers-reduced-motion: reduce) {
    .ui-panel-interactive, html :is(.ui-button, .ui-icon-button, .ui-filter) { transition: none; }
    .ui-switch-track, .ui-switch-track::after { transition: none; }
}

/* Climb identity stays consistent across the card grid and full-width list. */
.ui-climb-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 1rem; }
.ui-climb-grid:has(.ui-climb-response) { align-items: start; }
/* Shared responsive card grid for hills / lists / climbs / compute tiles:
   up to 4 across on wide screens (3 felt stretched), width-capped so the tiles
   don't blow up on ultra-wide monitors. */
.ui-card-grid { display: grid; gap: 1rem; grid-template-columns: minmax(0, 1fr); max-width: 108rem; }
@media (min-width: 640px)  { .ui-card-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1024px) { .ui-card-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 1280px) { .ui-card-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.ui-climb { position: relative; min-width: 0; }
.ui-climb-card { display: flex; flex-direction: column; gap: 0.75rem; padding: 1.125rem; }
.ui-climb [title] { position: relative; z-index: 1; }
.ui-climb-link::after { content: ''; position: absolute; inset: 0; border-radius: inherit; }
.ui-climb-link:focus-visible { outline: none; }
.ui-climb-link:focus-visible::after { outline: 2px solid rgb(var(--c-active-400)); outline-offset: -2px; }
.ui-climb-hill { display: flex; align-items: flex-start; gap: 0.375rem; margin: 0.25rem 0 0 1.875rem; font-size: 0.75rem; line-height: 1.125rem; }
.ui-climb-hill-link { position: relative; z-index: 1; min-width: 0; overflow-wrap: anywhere; color: rgb(var(--c-zinc-500)); text-decoration: none; text-underline-offset: 3px; }
.ui-climb-hill-link:hover { color: rgb(var(--c-active-400)); text-decoration: underline; }
.ui-climb-hill-link:focus-visible { outline: 2px solid rgb(var(--c-active-400)); outline-offset: 2px; }
.ui-climb-context a { position: relative; z-index: 1; }
.ui-climb-controls { position: relative; z-index: 1; min-width: 0; grid-column: 1 / -1; }
.ui-climb-response { overflow-wrap: anywhere; }
.ui-climb-list { overflow: hidden; }
.ui-climb-columns, .ui-climb-row { display: grid; grid-template-columns: minmax(0, 1fr) 9rem 7rem 6rem; align-items: center; gap: 1rem; padding: 1rem 1.125rem; }
.ui-climb-columns { background: rgb(var(--c-sidebar-900)); }
.ui-climb-row { border-top: 1px solid rgb(var(--c-zinc-800)); }
.ui-climb-row:hover, .ui-climb-row:focus-within { background: rgb(var(--c-zinc-800) / 0.2); box-shadow: none; }
.ui-climb-result, .ui-climb-age { text-align: right; }
.ui-climb-mobile-label { display: none; }
.ui-view-switch { display: inline-flex; padding: 2px; gap: 2px; border: 1px solid rgb(var(--c-zinc-700)); border-radius: var(--ui-radius-control); background: rgb(var(--c-zinc-900)); }
html .ui-view-switch .ui-button { min-height: 1.875rem; padding: 0.25rem 0.625rem; border: 0; border-radius: 0.25rem; background: transparent; color: rgb(var(--c-zinc-400)); }
html .ui-view-switch .ui-button[aria-pressed="true"] { background: rgb(var(--c-zinc-800) / 0.6); color: rgb(var(--c-zinc-100)); }
@media (min-width: 900px) {
    .ui-climb-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 1200px) {
    .ui-climb-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (min-width: 1280px) {
    .ui-climb-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
@media (max-width: 899px) {
    .ui-climb-columns { display: none; }
    .ui-climb-row { grid-template-columns: 1fr 1fr; gap: 0.75rem; }
    .ui-climb-row:first-of-type { border-top: 0; }
    .ui-climb-row > :first-child { grid-column: 1 / -1; }
    .ui-climb-age { grid-column: 1 / -1; text-align: left; }
    .ui-climb-mobile-label { display: inline; color: rgb(var(--c-zinc-500)); font-size: 0.75rem; }
}
@media (pointer: coarse) {
    html .ui-view-switch .ui-button { min-height: 44px; }
}

/* Local, persistent feedback for explicit saves. */
.ui-save-actions { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 0.75rem; min-width: 0; }
.ui-save-status { color: rgb(var(--c-zinc-400)); }
.ui-save-error { color: rgb(var(--c-red-400)); overflow-wrap: anywhere; }
.ui-save-status:empty { display: none; }
html .ui-save-button { position: relative; min-width: 7.5rem; flex-shrink: 0; }
.ui-save-measure { visibility: hidden; }
.ui-save-label { position: absolute; display: flex; align-items: center; gap: 0.4375rem; }
html .ui-save-button:disabled[aria-busy="true"] { opacity: 1; }
html .ui-save-button.ui-save-saved:disabled { opacity: 1; background: transparent; border-color: rgb(var(--c-brand-400)); color: rgb(var(--c-brand-400)); }
.ui-save-spinner { width: 0.875rem; height: 0.875rem; border: 1.5px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: ui-save-spin 0.8s linear infinite; }
@keyframes ui-save-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .ui-save-spinner { animation: none; } }
