﻿/* ============================================================
   ModbusDB — Industrial Dark Theme
   Ported from v0 Next.js template (oklch → hsl for compat)
   ============================================================ */

/* --- Fonts (Geist via Google CDN) --- */
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap');

/* ============================================================
   Design Tokens
   ============================================================ */
:root {
    /* Background / Surface */
    --background: #060911;          /* very dark blue-black */
    --foreground: #EFF0F4;          /* primary text / headings */
    --card: #101722;                /* raised card / table surface */
    --card-foreground: #EFF0F4;
    --popover: #0C121C;
    --popover-foreground: #EFF0F4;

    /* Hero — a touch lighter than the page background */
    --hero: #080E17;

    /* Primary — teal accent */
    --primary: #2EB4A1;
    --primary-foreground: #060911;

    /* Secondary — raised surface + body copy */
    --secondary: #1A2431;
    --secondary-foreground: #9AA3B0;

    /* Muted — subtle surface + metadata text */
    --muted: #141C28;
    --muted-foreground: #6E7887;

    /* Accent — bright teal for highlights / icons */
    --accent: #26C7B5;
    --accent-foreground: #060911;

    /* Destructive */
    --destructive: hsl(0 70% 45%);
    --destructive-foreground: hsl(0 0% 95%);

    /* Chrome */
    --border: #26313D;              /* subtle blue-grey border */
    --input: #0C121C;
    --ring: #2EB4A1;

    /* Dark-teal badge surface */
    --badge: #123D3D;
    --badge-foreground: #26C7B5;

    /* Radius */
    --radius: 0.5rem;

    /* Fonts */
    --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    --font-mono: 'JetBrains Mono', ui-monospace, 'Cascadia Code', Consolas, monospace;
}

/* ============================================================
   Reset & Base
   ============================================================ */
*,
*::before,
*::after {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
    border-color: var(--border);
}

html {
    font-size: 16px;
    -webkit-text-size-adjust: 100%;
    scroll-behavior: smooth;
}

/* FocusOnNavigate (Routes.razor) focuses the page <h1> on every navigation so screen
   reader and keyboard users land at the top of the new page rather than wherever they
   were. To be focusable the heading gets tabindex="-1", and the browser then paints its
   default outline right around the heading's block box.

   :not(:focus-visible) suppresses only that programmatic case. Anything a user actually
   focuses — by tab or by typing — still matches :focus-visible and keeps its ring, so the
   accessibility behaviour is untouched and only the stray outline goes. */
[tabindex="-1"]:focus:not(:focus-visible) {
    outline: none;
}

/* Every anchor on the site carries a class that sets its own colour. This is the safety
   net for any that doesn't: an unstyled link should land on the theme's accent, never on
   the browser's default blue, which is unreadable on this background. More specific rules
   (.navbar-links a, .row-link, th.sortable a, …) still win. */
a {
    color: var(--primary);
}

body {
    font-family: var(--font-sans);
    background-color: var(--background);
    color: var(--foreground);
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    min-height: 100vh;
}

/* ============================================================
   Layout Shell
   ============================================================ */
.app-shell {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
}

.app-main {
    flex: 1;
}

/* ============================================================
   Navbar
   ============================================================ */
.navbar {
    position: sticky;
    top: 0;
    z-index: 50;
    width: 100%;
    border-bottom: 1px solid var(--border);
    background: hsla(224, 48%, 5%, 0.95);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
}

.navbar-inner {
    max-width: 80rem;
    margin: 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    height: 4rem;
    padding: 0 1rem;
}

@media (min-width: 640px) {
    .navbar-inner { padding: 0 1.5rem; }
}
@media (min-width: 1024px) {
    .navbar-inner { padding: 0 2rem; }
}

.navbar-brand {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    text-decoration: none;
    color: var(--foreground);
}

/* Scaled by height alone, with width left to follow the intrinsic 250x83 so the wordmark
   can never be stretched. Same everywhere the logo appears.

   2.25rem puts the lockup at 108x36, near enough the ~110x24 the old icon-plus-text pair
   occupied: the wordmark spends most of its height on the mark, so matching the old height
   would have set the name several points smaller than the text it replaced. */
.navbar-brand img {
    height: 2.25rem;
    width: auto;
}

.navbar-links {
    display: none;
    align-items: center;
    gap: 1.5rem;
}

@media (min-width: 768px) {
    .navbar-links { display: flex; }
}

.navbar-links a {
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--muted-foreground);
    text-decoration: none;
    transition: color 0.15s ease;
}

.navbar-links a:hover {
    color: var(--foreground);
}

/* GitHub button in nav */
.btn-github {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.375rem 0.75rem;
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--foreground);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: transparent;
    text-decoration: none;
    transition: background 0.15s ease, border-color 0.15s ease;
    cursor: pointer;
}

.btn-github:hover {
    background: var(--secondary);
    border-color: var(--muted-foreground);
}

.btn-github svg {
    width: 1rem;
    height: 1rem;
}

/* Mobile menu toggle */
.navbar-mobile-toggle {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    border: none;
    background: transparent;
    color: var(--foreground);
    cursor: pointer;
    border-radius: var(--radius);
    transition: background 0.15s ease;
}

.navbar-mobile-toggle:hover {
    background: var(--secondary);
}

@media (min-width: 768px) {
    .navbar-mobile-toggle { display: none; }
}

.navbar-mobile-toggle svg {
    width: 1.25rem;
    height: 1.25rem;
}

/* Mobile dropdown */
.navbar-mobile-menu {
    border-top: 1px solid var(--border);
    background: var(--background);
    padding: 1rem;
}

@media (min-width: 768px) {
    .navbar-mobile-menu { display: none !important; }
}

.navbar-mobile-menu a {
    display: block;
    padding: 0.5rem 0;
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--muted-foreground);
    text-decoration: none;
    transition: color 0.15s ease;
}

.navbar-mobile-menu a:hover {
    color: var(--foreground);
}

/* ============================================================
   Hero Section
   ============================================================ */
.hero {
    position: relative;
    overflow: hidden;
    border-bottom: 1px solid var(--border);
    background: var(--hero);
    padding: 1.75rem 1rem;
}

@media (min-width: 640px) {
    .hero { padding: 2rem 1.5rem; }
}
@media (min-width: 1024px) {
    .hero { padding: 2rem 2rem; }
}

.hero-content {
    position: relative;
    max-width: 56rem;
    margin: 0 auto;
    text-align: center;
}

/* Landing hero: copy on the left, product imagery on the right. Stacks to one column
   below 1024px. Scoped to .hero-copy / .hero-media so the device-detail hero
   (.hero-device), which shares the .hero shell, is untouched. */
.hero-inner {
    position: relative;
    max-width: 80rem;
    margin: 0 auto;
    display: grid;
    grid-template-columns: 1fr;
    gap: 2.5rem;
    align-items: center;
}

@media (min-width: 1024px) {
    .hero-inner {
        grid-template-columns: 1.05fr 1fr;
        gap: 3.5rem;
    }
}

.hero-copy {
    text-align: left;
}

.hero-copy h1 {
    text-align: left;
}

.hero-accent {
    color: var(--primary);
}

.hero .hero-copy p {
    max-width: 40rem;
    margin: 1.5rem 0 0;
    text-align: left;
}

.hero-tagline {
    color: var(--primary);
}

.hero-media {
    position: relative;
    order: -1;                 /* image above the copy when stacked on mobile */
}

@media (min-width: 1024px) {
    .hero-media { order: 0; }  /* image to the right on desktop */
}

.hero-media img {
    display: block;
    width: 100%;
    height: auto;
}

/* The render sits on a dark-navy background a shade lighter than the hero surface, so it
   reads as a hard-edged rectangle if left alone. A blend mode won't rescue it
   (mix-blend-mode: lighten dropped the whole frame to an empty box; a mask-image feather
   silently failed to composite at 1x device-pixel-ratio). The reliable fix is a scrim:
   gradients painted in the hero colour on top of the image, dissolving the photo border
   into the background — the translucent-gradient blend the reference calls for.

   Four directional linear fades, one per edge, rather than a single radial: a radial big
   enough to keep the devices clear can't reach solid --hero at all four straight edges
   (its ends land on an ellipse, so the edge midpoints stay half-covered and the border
   shows through — the bug in the first attempt). Each linear ramps from transparent to
   solid --hero across the outer ~14%, so every edge pixel is exactly the hero colour and
   the seam disappears, while the centre — where the devices sit — is left untouched. */
.hero-media::after {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    background:
        linear-gradient(to top,    transparent 86%, var(--hero)),
        linear-gradient(to bottom, transparent 86%, var(--hero)),
        linear-gradient(to left,   transparent 86%, var(--hero)),
        linear-gradient(to right,  transparent 86%, var(--hero));
}

/* Floating "N+ Register Maps Available" figure, top-right over the imagery. Its own
   glassy card — no blend mode — so it stays crisp above the blended image. */
.hero-stat-badge {
    position: absolute;
    top: 1rem;
    right: 1rem;
    z-index: 1;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.7rem 1rem;
    background: hsla(224, 48%, 5%, 0.72);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
}

.hero-stat-badge svg {
    width: 1.5rem;
    height: 1.5rem;
    color: var(--primary);
    flex-shrink: 0;
}

.hero-stat-text {
    display: flex;
    flex-direction: column;
    line-height: 1.2;
}

.hero-stat-num {
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--foreground);
}

.hero-stat-label {
    font-size: 0.75rem;
    color: var(--muted-foreground);
}

/* Popular-search chips under the search bar. */
.hero-popular {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    margin-top: 1.25rem;
}

.hero-popular-label {
    font-size: 0.875rem;
    color: var(--muted-foreground);
    margin-right: 0.25rem;
}

.chip {
    display: inline-flex;
    align-items: center;
    padding: 0.3rem 0.75rem;
    font-size: 0.8rem;
    font-weight: 500;
    color: var(--primary);
    background: hsla(171, 60%, 44%, 0.08);
    border: 1px solid var(--border);
    border-radius: 9999px;
    text-decoration: none;
    transition: border-color 0.15s ease, background 0.15s ease;
}

.chip:hover {
    border-color: var(--primary);
    background: hsla(171, 60%, 44%, 0.15);
}

.hero-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.25rem 0.75rem;
    margin-bottom: 1.5rem;
    font-size: 0.75rem;
    font-weight: 500;
    color: var(--primary);
    background: hsla(171, 60%, 44%, 0.1);
    border: 1px solid hsla(171, 60%, 44%, 0.3);
    border-radius: 9999px;
}

.hero-badge svg {
    width: 0.75rem;
    height: 0.75rem;
}

.hero h1 {
    font-size: 2.25rem;
    font-weight: 700;
    letter-spacing: -0.03em;
    line-height: 1.1;
    color: var(--foreground);
    text-wrap: balance;
}

@media (min-width: 640px) {
    .hero h1 { font-size: 3rem; }
}
@media (min-width: 1024px) {
    .hero h1 { font-size: 3.75rem; }
}

.hero p {
    max-width: 42rem;
    margin: 1.5rem auto 0;
    font-size: 1.125rem;
    color: var(--muted-foreground);
    text-wrap: pretty;
}

@media (min-width: 640px) {
    .hero p { font-size: 1.25rem; }
}

/* Device detail hero — override centering */
.hero-device {
    text-align: left;
}

.hero-device h1 {
    text-wrap: unset;
}

.hero-device p {
    margin: 0.75rem 0 0;
    max-width: none;
}

.hero-stats {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 1.5rem;
    margin-top: 2.5rem;
    font-size: 0.875rem;
    color: var(--muted-foreground);
}

.hero-stat {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.hero-stat svg {
    width: 1rem;
    height: 1rem;
    color: var(--primary);
}

/* ============================================================
   Modbus Table Section
   ============================================================ */
.table-section {
    padding: 3rem 1rem;
}

@media (min-width: 640px) {
    .table-section { padding: 3rem 1.5rem; }
}
@media (min-width: 1024px) {
    .table-section { padding: 3rem 2rem; }
}

.table-container {
    max-width: 80rem;
    margin: 0 auto;
}

/* Toolbar: search + filters */
.table-toolbar {
    display: flex;
    flex-direction: column;
    gap: 1rem;
    margin-bottom: 2rem;
}

@media (min-width: 640px) {
    .table-toolbar {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
    }
}

.search-wrapper {
    position: relative;
    max-width: 28rem;
    flex: 1;
}

.search-wrapper svg {
    position: absolute;
    left: 0.75rem;
    top: 50%;
    transform: translateY(-50%);
    width: 1rem;
    height: 1rem;
    color: var(--muted-foreground);
    pointer-events: none;
}

.search-input {
    width: 100%;
    padding: 0.5rem 0.75rem 0.5rem 2.5rem;
    font-size: 0.875rem;
    font-family: var(--font-sans);
    color: var(--foreground);
    background: var(--input);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    outline: none;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.search-input::placeholder {
    color: var(--muted-foreground);
}

.search-input:focus {
    border-color: var(--ring);
    box-shadow: 0 0 0 2px hsla(171, 60%, 44%, 0.2);
}

/* Category filter pills */
.filter-bar {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.filter-bar svg {
    width: 1rem;
    height: 1rem;
    color: var(--muted-foreground);
    flex-shrink: 0;
}

.filter-pills {
    display: flex;
    gap: 0.25rem;
    flex-wrap: wrap;
}

/* Anchors, not buttons: filtering is a navigation under static SSR. */
.filter-pill {
    display: inline-block;
    padding: 0.25rem 0.75rem;
    font-size: 0.75rem;
    font-weight: 500;
    font-family: var(--font-sans);
    border: none;
    border-radius: var(--radius);
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease;
    background: transparent;
    color: var(--muted-foreground);
    text-decoration: none;
}

.filter-pill:hover {
    background: var(--secondary);
    color: var(--foreground);
}

.filter-pill.active {
    background: var(--primary);
    color: var(--primary-foreground);
}

/* Results count */
.results-count {
    margin-bottom: 1rem;
    font-size: 0.875rem;
    color: var(--muted-foreground);
}

/* Table chrome */
.table-card {
    overflow: hidden;
    border-radius: var(--radius);
    border: 1px solid var(--border);
    background: var(--card);
}

.table-scroll {
    overflow-x: auto;
}

.data-table {
    width: 100%;
    border-collapse: collapse;
}

.data-table thead tr {
    border-bottom: 1px solid var(--border);
    background: hsla(216, 33%, 12%, 0.5);
}

.data-table th {
    padding: 0.75rem 1rem;
    text-align: left;
    font-size: 0.75rem;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--muted-foreground);
    white-space: nowrap;
    user-select: none;
}

/* The heading's anchor carries the click target; the th keeps the cell padding, so the
   anchor is stretched to fill it and stays a full-size hit area. */
.data-table th.sortable {
    padding: 0;
    transition: color 0.15s ease;
}

.data-table th.sortable a {
    display: block;
    padding: 0.75rem 1rem;
    color: inherit;
    text-decoration: none;
    white-space: nowrap;
}

.data-table th.sortable:hover {
    color: var(--foreground);
}

.data-table th.sortable a:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: -2px;
}

.data-table th svg {
    display: inline;
    width: 1rem;
    height: 1rem;
    margin-left: 0.25rem;
    vertical-align: middle;
}

.data-table tbody tr {
    border-bottom: 1px solid var(--border);
    transition: background 0.12s ease;
}

.data-table tbody tr:last-child {
    border-bottom: none;
}

.data-table tbody tr:hover {
    background: hsla(216, 33%, 12%, 0.3);
}

.data-table td {
    padding: 1rem;
    font-size: 0.875rem;
    white-space: nowrap;
    color: var(--foreground);
}

.data-table td.muted {
    color: var(--muted-foreground);
}

.data-table td.mono {
    font-family: var(--font-mono);
    color: var(--muted-foreground);
}

.data-table td.bold {
    font-weight: 500;
}

/* Wrapping cells. `.data-table td` is nowrap so the numeric and badge columns stay on one
   line and the table scrolls horizontally rather than reflowing; prose columns —
   Description, Vendor Notes — are the exception. Without this a 400-character vendor note
   is one enormous line and every other column is pushed off-screen.

   max-width with a table-layout of auto is a hint, not a hard cap: the browser honours it
   while it can and grows the column when the rest of the row leaves room. overflow-wrap
   handles the pathological case of an unbroken token (a long tag name, a URL) that would
   otherwise overflow the cell rather than wrap inside it. */
.data-table td.wrap {
    white-space: normal;
    overflow-wrap: anywhere;
    min-width: 14rem;
    max-width: 28rem;
}

/* Vendor notes are supporting detail, not the row's subject: narrower than Description
   and set slightly smaller so a long note cannot dominate the row it belongs to. */
.data-table td.wrap-notes {
    white-space: normal;
    overflow-wrap: anywhere;
    min-width: 10rem;
    max-width: 22rem;
    font-size: 0.8125rem;
}

/* Vertical rhythm: once cells can be several lines tall, bottom-aligned content in the
   short columns of the same row looks detached from it. */
.data-table tbody td {
    vertical-align: top;
}

/* Category badge inside table */
.category-badge {
    display: inline-flex;
    align-items: center;
    padding: 0.125rem 0.5rem;
    font-size: 0.75rem;
    font-weight: 500;
    color: var(--primary);
    background: hsla(171, 60%, 44%, 0.1);
    border-radius: calc(var(--radius) - 2px);
}

/* Download dropdown */
.download-cell {
    text-align: right;
}

.btn-download {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.375rem 0.625rem;
    font-size: 0.875rem;
    font-family: var(--font-sans);
    color: var(--foreground);
    background: transparent;
    border: none;
    border-radius: var(--radius);
    cursor: pointer;
    transition: background 0.15s ease;
}

.btn-download:hover {
    background: var(--secondary);
}

.btn-download svg {
    width: 1rem;
    height: 1rem;
}

/* Download dropdown menu */
.dropdown {
    position: relative;
    display: inline-block;
}

.dropdown-menu {
    display: none;
    position: absolute;
    right: 0;
    top: 100%;
    z-index: 40;
    min-width: 10rem;
    margin-top: 0.25rem;
    padding: 0.25rem;
    background: var(--popover);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: 0 10px 30px -5px rgba(0, 0, 0, 0.4);
}

.dropdown.open .dropdown-menu {
    display: block;
}

.dropdown-item {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    width: 100%;
    padding: 0.5rem 0.75rem;
    font-size: 0.875rem;
    font-family: var(--font-sans);
    color: var(--foreground);
    background: transparent;
    border: none;
    border-radius: calc(var(--radius) - 2px);
    cursor: pointer;
    transition: background 0.12s ease;
    text-align: left;
}

.dropdown-item:hover {
    background: var(--secondary);
}

.dropdown-item svg {
    width: 1rem;
    height: 1rem;
    color: var(--muted-foreground);
}

/* Hidden columns on mobile */
@media (max-width: 639px) {
    .hide-mobile { display: none; }
}

/* Empty state */
.empty-state {
    padding: 3rem 1rem;
    text-align: center;
    color: var(--muted-foreground);
}

/* ============================================================
   Footer
   ============================================================ */
.site-footer {
    border-top: 1px solid var(--border);
    background: var(--card);
    padding: 3rem 1rem;
}

@media (min-width: 640px) {
    .site-footer { padding: 3rem 1.5rem; }
}
@media (min-width: 1024px) {
    .site-footer { padding: 3rem 2rem; }
}

.footer-inner {
    max-width: 80rem;
    margin: 0 auto;
}

.footer-brand {
    display: flex;
    /* Centred, not left-aligned as it was in the old three-column footer: the mark is the
       footer's only content now, sitting directly above the centred bottom line. */
    justify-content: center;
    align-items: center;
    gap: 0.5rem;
}

.footer-brand img {
    height: 2.25rem;
    width: auto;
}

.footer-bottom {
    margin-top: 2rem;
    padding-top: 2rem;
    border-top: 1px solid var(--border);
    text-align: center;
    font-size: 0.875rem;
    color: var(--muted-foreground);
}

/* ============================================================
   Hero Search Bar
   ============================================================ */
.hero-search {
    display: flex;
    max-width: 36rem;
    margin: 1.5rem auto 0;
    gap: 0.5rem;
}

/* In the landing hero the search sits in the left column, so it aligns left rather
   than centring under a full-width heading. */
.hero-copy .hero-search {
    margin-left: 0;
    margin-right: 0;
}

.hero-search .search-wrapper {
    flex: 1;
    max-width: none;
}

.hero-search .search-input {
    height: 2.75rem;
    font-size: 1rem;
    color: var(--foreground);
    background: var(--input);
    border: 1px solid var(--border);
}

.btn-search {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    height: 2.75rem;
    padding: 0 1.25rem;
    font-size: 0.875rem;
    font-weight: 600;
    font-family: var(--font-sans);
    color: var(--primary-foreground);
    background: var(--primary);
    border: none;
    border-radius: var(--radius);
    cursor: pointer;
    transition: opacity 0.15s ease;
    white-space: nowrap;
}

.btn-search:hover {
    opacity: 0.9;
}

.btn-search svg {
    width: 1rem;
    height: 1rem;
}

/* ============================================================
   Report Issue Modal
   ============================================================ */
/* A :target modal — hidden until the URL fragment names it, revealed by CSS alone. This
   is what lets the device page report an issue without a Blazor circuit or any script.
   Any link to "#" clears the target and closes it. */
.modal-overlay {
    position: fixed;
    inset: 0;
    z-index: 100;
    display: none;
    align-items: center;
    justify-content: center;
    background: hsla(224, 50%, 4%, 0.8);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
}

.modal-overlay:target {
    display: flex;
}

/* Click-anywhere-outside close. Sits behind the card, covering the backdrop. */
.modal-backdrop {
    position: absolute;
    inset: 0;
    cursor: default;
}

.modal-card {
    position: relative;
}

.modal-card {
    width: 100%;
    max-width: 32rem;
    margin: 1rem;
    padding: 1.5rem;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
}

.modal-card h2 {
    font-size: 1.25rem;
    font-weight: 600;
    color: var(--foreground);
    margin-bottom: 1.25rem;
}

.modal-card label {
    display: block;
    font-size: 0.8125rem;
    font-weight: 500;
    color: var(--muted-foreground);
    margin-bottom: 0.375rem;
}

.modal-card select,
.modal-card textarea {
    width: 100%;
    padding: 0.5rem 0.75rem;
    font-size: 0.875rem;
    font-family: var(--font-sans);
    color: var(--foreground);
    background: var(--input);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    outline: none;
    transition: border-color 0.15s ease;
    margin-bottom: 1rem;
}

.modal-card select:focus,
.modal-card textarea:focus {
    border-color: var(--ring);
    box-shadow: 0 0 0 2px hsla(171, 60%, 44%, 0.2);
}

.modal-card textarea {
    min-height: 6rem;
    resize: vertical;
}

.modal-actions {
    display: flex;
    justify-content: flex-end;
    gap: 0.5rem;
    margin-top: 0.5rem;
}

.btn-ghost {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 2.25rem;
    padding: 0 1rem;
    font-size: 0.875rem;
    font-weight: 500;
    font-family: var(--font-sans);
    color: var(--muted-foreground);
    background: transparent;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease;
}

.btn-ghost:hover {
    background: var(--secondary);
    color: var(--foreground);
}

.btn-submit {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 2.25rem;
    padding: 0 1rem;
    font-size: 0.875rem;
    font-weight: 600;
    font-family: var(--font-sans);
    color: var(--primary-foreground);
    background: var(--primary);
    border: none;
    border-radius: var(--radius);
    cursor: pointer;
    transition: opacity 0.15s ease;
}

.btn-submit:hover {
    opacity: 0.9;
}

.btn-submit:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

/* Report icon button */
.btn-report {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    height: 2.75rem;
    padding: 0 1rem;
    font-size: 0.875rem;
    font-weight: 500;
    font-family: var(--font-sans);
    color: var(--muted-foreground);
    background: transparent;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.btn-report:hover {
    background: var(--secondary);
    color: var(--foreground);
    border-color: var(--muted-foreground);
}

.btn-report svg {
    width: 1rem;
    height: 1rem;
}

/* Success message */
.report-success {
    padding: 0.75rem 1rem;
    font-size: 0.875rem;
    color: var(--primary);
    background: hsla(171, 60%, 44%, 0.1);
    border: 1px solid hsla(171, 60%, 44%, 0.3);
    border-radius: var(--radius);
    text-align: center;
}

/* ============================================================
   Register Gate (auth wall)
   ============================================================ */
.blurred-row td {
    position: relative;
}

.blur-text {
    filter: blur(5px);
    user-select: none;
    pointer-events: none;
    opacity: 0.4;
}

/* Height tracks DeviceDetail's BlurredPlaceholderRows: a data-table row is roughly
   3.4rem (1rem padding top and bottom plus the line box), so 20 placeholder rows span
   about 68rem and 40rem of gradient fades the lower ~60% of them — the same proportion
   16rem gave against the 8 rows this replaced. Raise both together, or the placeholders
   sit outside the fade as a flat band of blurred text.

   pointer-events stays none so the taller overlay cannot swallow clicks on the real
   rows it now reaches over; the card re-enables them for itself. */
.gate-overlay {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    height: 40rem;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    padding-bottom: 2rem;
    background: linear-gradient(to bottom, transparent 0%, var(--background) 70%);
    pointer-events: none;
    z-index: 10;
}

.gate-card {
    pointer-events: auto;
    text-align: center;
    padding: 1.5rem 2rem;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.4);
    max-width: 28rem;
}

/* ============================================================
   Utility
   ============================================================ */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border-width: 0;
}

/* ============================================================
   Blazor-specific overrides
   ============================================================ */
#blazor-error-ui {
    background: var(--destructive);
    color: var(--destructive-foreground);
    bottom: 0;
    box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.3);
    display: none;
    left: 0;
    padding: 0.75rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
    text-align: center;
}

#blazor-error-ui .dismiss {
    cursor: pointer;
    position: absolute;
    right: 0.75rem;
    top: 0.5rem;
}

.blazor-reconnect-modal {
    display: none;
}

.components-reconnect-show .blazor-reconnect-modal {
    display: flex;
    align-items: center;
    justify-content: center;
    position: fixed;
    inset: 0;
    z-index: 9999;
    background: hsla(224, 48%, 5%, 0.8);
    backdrop-filter: blur(4px);
    color: var(--muted-foreground);
    font-size: 0.875rem;
}

/* ============================================================
   Admin dashboard
   Operational screens. Reuses the existing tokens and table
   styling; adds only the stat grid and tab strip.
   ============================================================ */
/* Sidebar shell (AdminLayout / AdminSidebar) */
.admin-shell, .portal-shell {
    display: flex;
    min-height: 100vh;
    background: var(--background);
}

.admin-sidebar, .portal-sidebar {
    position: sticky;
    top: 0;
    align-self: flex-start;
    height: 100vh;
    width: 232px;
    flex: none;
    display: flex;
    flex-direction: column;
    gap: 1rem;
    padding: 1.25rem 0;
    background: var(--card);
    border-right: 1px solid var(--border);
    overflow-y: auto;
}

.admin-brand, .portal-brand {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0 1.25rem;
    text-decoration: none;
    color: var(--foreground);
}

.admin-brand img, .portal-brand img {
    height: 2rem;
    width: auto;
    flex: none;
}

.admin-brand-sub, .portal-brand-sub {
    font-size: 0.7rem;
    font-weight: 500;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--muted-foreground);
}

.admin-nav, .portal-nav {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    padding: 0 0.6rem;
}

.admin-nav-heading, .portal-nav-heading {
    margin: 1rem 0.6rem 0.25rem;
    font-size: 0.68rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--muted-foreground);
}

.admin-nav-link, .portal-nav-link {
    display: flex;
    align-items: center;
    gap: 0.65rem;
    padding: 0.5rem 0.65rem;
    border-radius: var(--radius);
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--muted-foreground);
    text-decoration: none;
    transition: color 0.15s ease, background 0.15s ease;
}

.admin-nav-link svg, .portal-nav-link svg {
    flex: none;
}

.admin-nav-link:hover, .portal-nav-link:hover {
    color: var(--foreground);
    background: var(--secondary);
}

.admin-nav-link.active, .portal-nav-link.active {
    color: var(--primary);
    background: hsl(171 60% 44% / 0.12);
}

.admin-sidebar-footer, .portal-sidebar-footer {
    margin-top: auto;
    padding: 0.75rem 1.25rem 0;
    border-top: 1px solid var(--border);
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}

.admin-user, .portal-user {
    font-size: 0.8125rem;
    color: var(--muted-foreground);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.admin-sidebar-action, .portal-sidebar-action {
    font-size: 0.8125rem;
    font-weight: 500;
    color: var(--muted-foreground);
    text-decoration: none;
    transition: color 0.15s ease;
}

.admin-sidebar-action:hover, .portal-sidebar-action:hover {
    color: var(--foreground);
}

.admin-main, .portal-main {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
}

@media (max-width: 820px) {
    .admin-shell, .portal-shell {
        flex-direction: column;
    }

    .admin-sidebar, .portal-sidebar {
        position: static;
        height: auto;
        width: auto;
        flex-direction: row;
        align-items: center;
        gap: 1rem;
        padding: 0.6rem 1rem;
        overflow-x: auto;
        border-right: none;
        border-bottom: 1px solid var(--border);
    }

    .admin-brand, .portal-brand {
        padding: 0;
    }
    .admin-brand br, .portal-brand br { display: none; }
    .admin-brand-sub, .portal-brand-sub { display: none; }

    .admin-nav, .portal-nav {
        flex-direction: row;
        flex-wrap: nowrap;
        padding: 0;
        gap: 0.15rem;
    }
    .admin-nav-heading, .portal-nav-heading { display: none; }
    .admin-nav-link span, .portal-nav-link span { display: none; }
    .admin-nav-link, .portal-nav-link { padding: 0.5rem; }

    .admin-sidebar-footer, .portal-sidebar-footer {
        margin: 0 0 0 auto;
        padding: 0;
        border-top: none;
        flex-direction: row;
        gap: 0.75rem;
        white-space: nowrap;
    }
    .admin-user, .portal-user { display: none; }
}

.admin-header {
    padding: 2rem 2rem 0;
}

.admin-title {
    font-size: 1.5rem;
    color: var(--foreground);
    margin-bottom: 1rem;
}

.admin-tabs {
    display: flex;
    gap: 0.25rem;
    border-bottom: 1px solid var(--border);
    overflow-x: auto;
}

.admin-tab {
    padding: 0.625rem 1rem;
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--muted-foreground);
    text-decoration: none;
    white-space: nowrap;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
    transition: color 0.15s ease, border-color 0.15s ease;
}

.admin-tab:hover {
    color: var(--foreground);
}

.admin-tab.active {
    color: var(--primary);
    border-bottom-color: var(--primary);
}

.stat-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
    gap: 1rem;
    padding: 1.5rem 2rem 0;
}

.stat-card {
    padding: 1rem 1.25rem;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
}

.stat-label {
    font-size: 0.75rem;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--muted-foreground);
}

.stat-value {
    font-family: var(--font-mono);
    font-size: 1.75rem;
    font-weight: 600;
    color: var(--foreground);
    line-height: 1.2;
    margin-top: 0.375rem;
}

.stat-value.accent {
    color: var(--primary);
}

.stat-sub {
    font-size: 0.75rem;
    color: var(--muted-foreground);
    margin-top: 0.25rem;
}

.admin-section {
    padding: 1.5rem 2rem;
}

.admin-section h2 {
    font-size: 1rem;
    color: var(--foreground);
    margin-bottom: 0.75rem;
}

.admin-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.75rem;
    margin-bottom: 1rem;
}

.admin-toolbar label {
    font-size: 0.8125rem;
    color: var(--muted-foreground);
}

.admin-toolbar input[type="date"],
.admin-toolbar input[type="text"],
.admin-toolbar select {
    padding: 0.375rem 0.5rem;
    font-size: 0.8125rem;
    font-family: inherit;
    color: var(--foreground);
    background: var(--input);
    border: 1px solid var(--border);
    border-radius: var(--radius);
}

.admin-toolbar input:focus,
.admin-toolbar select:focus {
    outline: 2px solid var(--ring);
    outline-offset: -1px;
}

.checkbox-label {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    cursor: pointer;
}

.feed-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.75rem;
    height: 1.75rem;
    border-radius: 50%;
    background: var(--muted);
    color: var(--primary);
    flex-shrink: 0;
}

.pill {
    display: inline-block;
    padding: 0.125rem 0.5rem;
    font-size: 0.6875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    border-radius: 999px;
    background: var(--muted);
    color: var(--muted-foreground);
}

.pill.open {
    background: hsl(38 90% 50% / 0.15);
    color: hsl(38 90% 60%);
}

.pill.resolved {
    background: hsl(171 60% 44% / 0.15);
    color: var(--primary);
}

.pill.miss {
    background: hsl(0 70% 45% / 0.15);
    color: hsl(0 70% 65%);
}

@media (max-width: 640px) {
    .admin-header,
    .stat-grid,
    .admin-section {
        padding-left: 1rem;
        padding-right: 1rem;
    }
}


/* ============================================================
   Static SSR link chrome
   Sorting, filtering, paging and row navigation are all plain anchors now, so the
   styles that used to live in inline style="" attributes on buttons live here.
   ============================================================ */

/* Device links inside a table row read as text, not as links. */
.row-link {
    color: var(--foreground);
    text-decoration: none;
}

.row-link:hover {
    color: var(--primary);
}

/* "Clear search" / "Browse all" beside the results count. */
.text-link {
    color: var(--primary);
    text-decoration: none;
}

.text-link:hover {
    text-decoration: underline;
}

/* Pagination */
.pagination {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 1rem;
    margin-top: 1.25rem;
}

.page-link {
    display: inline-flex;
    align-items: center;
    padding: 0.375rem 0.875rem;
    font-size: 0.8125rem;
    font-weight: 500;
    color: var(--foreground);
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    text-decoration: none;
    transition: background 0.15s ease, color 0.15s ease;
}

.page-link:hover {
    background: var(--secondary);
}

.page-link.disabled {
    color: var(--muted-foreground);
    opacity: 0.5;
    pointer-events: none;
}

.page-status {
    font-size: 0.8125rem;
    color: var(--muted-foreground);
}

/* Outcome banner for a form round-trip (e.g. ?reported=1 after an issue report).
   Replaces the in-modal success/failure state, which needed a live component to show. */
.page-banner {
    max-width: 72rem;
    margin: 1rem auto 0;
    padding: 0.75rem 1rem;
    font-size: 0.875rem;
    border-radius: var(--radius);
    border: 1px solid var(--border);
}

.page-banner.success {
    color: var(--foreground);
    background: hsla(171, 60%, 44%, 0.12);
    border-color: hsla(171, 60%, 44%, 0.4);
}

.page-banner.error {
    color: var(--destructive-foreground);
    background: var(--destructive);
    border-color: var(--destructive);
}

/* The Report Issue trigger is an anchor now, not a button. */
a.btn-report {
    text-decoration: none;
}

/* ── Firmware selector ───────────────────────────────────────────────────
   A device model that ships several firmware revisions is several device rows, each with
   its own register map. This picks between them.

   <details>, not <select>: the device page is static SSR with no circuit and no script, so
   a <select> would have nothing to act on its change event. The menu holds ordinary
   anchors, which also means a crawler discovers the other revisions by following them. */
.fw-select {
    position: relative;
    display: inline-block;
    vertical-align: middle;
}

.fw-select > summary {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.3125rem 0.75rem;
    font-size: 0.875rem;
    color: var(--foreground);
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    cursor: pointer;
    user-select: none;
    list-style: none;
}

/* The default disclosure triangle, in both engines. The chevron in the markup replaces it,
   so it can sit after the value rather than before the label. */
.fw-select > summary::-webkit-details-marker { display: none; }
.fw-select > summary::marker { content: ""; }

.fw-select > summary:hover {
    background: var(--secondary);
}

.fw-select > summary:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}

.fw-select-caption {
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--muted-foreground);
}

.fw-select-value {
    font-weight: 500;
}

.fw-select[open] > summary svg {
    transform: rotate(180deg);
}

.fw-select-menu {
    position: absolute;
    z-index: 20;
    top: calc(100% + 0.25rem);
    left: 0;
    min-width: 16rem;
    margin: 0;
    padding: 0.25rem;
    list-style: none;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: 0 8px 24px hsla(224, 50%, 3%, 0.45);
}

.fw-select-menu a {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.5rem 0.625rem;
    font-size: 0.875rem;
    color: var(--foreground);
    text-decoration: none;
    border-radius: calc(var(--radius) - 2px);
}

.fw-select-menu a:hover {
    background: var(--secondary);
}

.fw-select-menu a.active {
    color: var(--primary);
    font-weight: 500;
}

/* Register counts are here because a revision carrying far fewer registers than its
   siblings is usually a half-finished upload rather than a genuinely smaller map. */
.fw-select-count {
    font-size: 0.75rem;
    color: var(--muted-foreground);
    font-family: var(--font-mono);
}

/* Listing badge: this row stands for a product with several firmware revisions, so the
   register count beside it is one revision's, not the whole product's. */
.fw-badge {
    display: inline-block;
    margin-left: 0.5rem;
    padding: 0.0625rem 0.375rem;
    font-size: 0.6875rem;
    font-weight: 500;
    color: var(--muted-foreground);
    background: var(--secondary);
    border: 1px solid var(--border);
    border-radius: 999px;
    white-space: nowrap;
}

/* ── Firmware comparison ─────────────────────────────────────────────────
   /compare/{vendor}/{family}/{model}. Two revisions of one device's register map, matched
   on address and function code. */
.compare-picker {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.625rem;
    padding: 1rem;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
}

.compare-picker label {
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--muted-foreground);
}

.compare-picker select {
    padding: 0.375rem 0.5rem;
    font-size: 0.875rem;
    font-family: inherit;
    color: var(--foreground);
    background: var(--background);
    border: 1px solid var(--border);
    border-radius: var(--radius);
}

.compare-picker-arrow {
    color: var(--muted-foreground);
}

.diff-summary {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 1rem;
    font-size: 0.8125rem;
    color: var(--muted-foreground);
}

.diff-stat {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
}

/* A dot rather than coloured text: the counts stay legible at small sizes, and colour is
   never the only carrier of the meaning — the word beside it says which is which. */
.diff-stat::before {
    content: "";
    width: 0.5rem;
    height: 0.5rem;
    border-radius: 50%;
    background: var(--muted-foreground);
}

.diff-stat.added::before { background: hsl(152, 55%, 45%); }
.diff-stat.removed::before { background: hsl(0, 65%, 58%); }
.diff-stat.changed::before { background: hsl(38, 85%, 55%); }

.diff-tag {
    display: inline-block;
    padding: 0.0625rem 0.4375rem;
    font-size: 0.6875rem;
    font-weight: 500;
    border-radius: 999px;
    white-space: nowrap;
    border: 1px solid var(--border);
    color: var(--muted-foreground);
}

.diff-tag.added {
    color: hsl(152, 55%, 45%);
    background: hsla(152, 55%, 45%, 0.12);
    border-color: hsla(152, 55%, 45%, 0.3);
}

.diff-tag.removed {
    color: hsl(0, 65%, 62%);
    background: hsla(0, 65%, 58%, 0.12);
    border-color: hsla(0, 65%, 58%, 0.3);
}

.diff-tag.changed {
    color: hsl(38, 85%, 58%);
    background: hsla(38, 85%, 55%, 0.12);
    border-color: hsla(38, 85%, 55%, 0.3);
}

/* A left border marks the row's status down its whole height, which matters because a
   changed row can be several lines tall once its differing fields are listed out. */
.diff-row.added { box-shadow: inset 3px 0 0 hsla(152, 55%, 45%, 0.7); }
.diff-row.removed { box-shadow: inset 3px 0 0 hsla(0, 65%, 58%, 0.7); }
.diff-row.changed { box-shadow: inset 3px 0 0 hsla(38, 85%, 55%, 0.7); }

.diff-field {
    display: flex;
    gap: 0.5rem;
    padding: 0.125rem 0;
}

.diff-field-name {
    flex: 0 0 6.5rem;
    font-size: 0.6875rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--muted-foreground);
}

.diff-old {
    color: hsl(0, 55%, 68%);
    text-decoration: line-through;
    text-decoration-color: hsla(0, 55%, 68%, 0.5);
}

.diff-new {
    color: hsl(152, 45%, 60%);
}

/* ── Portal page chrome ──────────────────────────────────────────────────
   The body of a page inside the sidebar shell. Admin screens each roll their own padding;
   these are the shared ones the Library uses. */
.portal-page {
    padding: 2rem;
    max-width: 80rem;
}

.portal-page-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1.5rem;
    flex-wrap: wrap;
    margin-bottom: 1.5rem;
}

.portal-page-header h1 {
    font-size: 1.5rem;
    color: var(--foreground);
    margin: 0.25rem 0 0.375rem;
}

.portal-page-header p {
    font-size: 0.875rem;
    color: var(--muted-foreground);
    margin: 0;
    max-width: 46rem;
}

/* Destructive confirm. Distinct from .btn-report so "Delete" is never one careless click
   away from looking like every other action in the row. */
.btn-danger {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.375rem 0.75rem;
    font-size: 0.8125rem;
    font-weight: 500;
    font-family: inherit;
    color: hsl(0, 70%, 92%);
    background: hsl(0, 62%, 42%);
    border: 1px solid hsl(0, 62%, 48%);
    border-radius: var(--radius);
    cursor: pointer;
    text-decoration: none;
    transition: background 0.15s ease;
}

.btn-danger:hover {
    background: hsl(0, 62%, 48%);
}

.btn-danger:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}

/* .btn-ghost is a <button> in the admin tools and an <a> in the Library's row actions. */
a.btn-ghost {
    text-decoration: none;
}

/* ── Register search, on the device page ─────────────────────────────────
   A GET form, not a live filter: the page is static SSR, so the search term travels in the
   URL and the result is a normal page load. That also makes a search shareable. */
.register-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem 1.5rem;
    margin-bottom: 0.75rem;
}

.register-search {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.25rem 0.25rem 0.25rem 0.75rem;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
}

.register-search svg {
    color: var(--muted-foreground);
    flex-shrink: 0;
}

.register-search input {
    width: 22rem;
    max-width: 50vw;
    padding: 0.375rem 0;
    font-size: 0.875rem;
    font-family: inherit;
    color: var(--foreground);
    background: transparent;
    border: none;
    outline: none;
}

.register-search input::placeholder {
    color: var(--muted-foreground);
}

/* The form owns the focus ring, so focusing the borderless input still reads as focused. */
.register-search:focus-within {
    border-color: var(--primary);
}

/* Visible to a screen reader, not on screen. The magnifier and the placeholder carry the
   meaning visually; the label has to exist for anyone not seeing them. */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border-width: 0;
}
