/* ============================================================================ Jorge Cuadros & Asociados — design system Warm coastal-professional identity for a Baja California firm. Fraunces (display serif) + Work Sans (UI) + JetBrains Mono (data). Palette: cream paper, deep pine brand, terracotta accent, gold = Servicios, teal = Seguros, aubergine = Fideicomiso. ========================================================================== */ :root { /* neutrals — warm paper family */ --paper: #f5f1e8; --paper-2: #efe9dc; --surface: #fffefb; --surface-2: #faf6ee; --line: #e4dccb; --line-strong: #d3c8b1; /* ink / text */ --ink: #211d17; --ink-soft: #4b4438; --muted: #756c5c; --muted-2: #98907e; /* brand — deep pine teal */ --brand-900: #0c322d; --brand-800: #113f38; --brand-700: #16544a; --brand-600: #1c6b5e; --brand-500: #24897a; --brand-tint: #e2ede9; /* accent — terracotta clay (CTA / focus / links) */ --accent: #bf5a34; --accent-600: #a94c2a; --accent-tint: #f6e4da; /* line-of-business + domains */ --servicios: #9a6a12; /* gold / ochre — utilities */ --servicios-tint: #f2e6c8; --servicios-ink: #6d4a08; --seguros: #0f6f68; /* teal — insurance */ --seguros-tint: #d3ebe7; --seguros-ink: #0a4b46; --fideicomiso: #6d3f60; /* aubergine — trust */ --fideicomiso-tint: #eddced; --fideicomiso-ink: #4a2a41; /* semantic */ --positive: #2f6d3c; --positive-tint: #dcecdd; --negative: #a23a2c; --negative-tint: #f4dcd6; /* shape + motion */ --radius-sm: 6px; --radius: 10px; --radius-lg: 16px; --shadow-sm: 0 1px 2px rgba(33, 29, 23, 0.06), 0 1px 3px rgba(33, 29, 23, 0.05); --shadow: 0 2px 4px rgba(33, 29, 23, 0.05), 0 8px 24px -12px rgba(33, 29, 23, 0.18); --shadow-lg: 0 24px 60px -24px rgba(12, 50, 45, 0.35); --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1); --ease-out-quart: cubic-bezier(0.25, 1, 0.5, 1); --font-display: "Fraunces", "Iowan Old Style", "Palatino Linotype", Georgia, serif; --font-sans: "Work Sans", system-ui, -apple-system, "Segoe UI", sans-serif; --font-mono: "JetBrains Mono", ui-monospace, "SF Mono", "Cascadia Code", Menlo, monospace; --shell-max: 1180px; } * { box-sizing: border-box; } html, body { margin: 0; padding: 0; } /* ---------------------------------------------------------------------------- User-adjustable text size. Every font-size in this stylesheet is expressed in rem, so the whole UI follows the root size and one variable scales it all. --ui-scale is written onto by the pre-hydration script in layout.tsx (read from localStorage, so there is no flash of the wrong size) and updated live by the Aa control in the appbar. A percentage keeps the browser's own base font size honoured instead of hard-coding 16px over it. -------------------------------------------------------------------------- */ html { font-size: calc(100% * var(--ui-scale, 1)); } body { font-family: var(--font-sans); background-color: var(--paper); /* subtle paper grain via layered radial dots */ background-image: radial-gradient( circle at 1px 1px, rgba(33, 29, 23, 0.035) 1px, transparent 0 ); background-size: 22px 22px; color: var(--ink); font-size: 0.9375rem; line-height: 1.55; -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; } h1, h2, h3, h4 { font-family: var(--font-display); font-weight: 560; color: var(--ink); letter-spacing: -0.01em; margin: 0; line-height: 1.12; } a { color: var(--accent-600); text-decoration: none; } a:hover { text-decoration: underline; } button { font-family: inherit; cursor: pointer; } :focus-visible { outline: 2.5px solid var(--accent); outline-offset: 2px; border-radius: 4px; } .mono { font-family: var(--font-mono); font-feature-settings: "tnum" 1; } /* ---- layout helpers ---- */ .shell-main { max-width: var(--shell-max); margin: 0 auto; padding: 2.125rem 1.75rem 6rem; } @media (max-width: 640px) { .shell-main { padding: 1.375rem 1rem 4.5rem; } } /* Deployed-build line. Quiet by default — it only needs to be legible when someone is verifying a release or a rollback. */ .shell-footer { max-width: var(--shell-max); margin: 0 auto; padding: 1rem 1.75rem 1.75rem; display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.75rem; font-size: 0.75rem; color: var(--muted-2); border-top: 1px solid var(--line); } .shell-footer-build { font-family: var(--font-mono); font-variant-numeric: tabular-nums; cursor: help; /* Full 40-char commit hashes, and two of them when the tiers disagree. Hex offers no break opportunity, so without this the line pushes the page into horizontal scroll on a phone. */ min-width: 0; overflow-wrap: anywhere; } .shell-footer-warn { color: var(--negative); background: var(--negative-tint); border-radius: var(--radius-sm); padding: 0.0625rem 0.375rem; font-weight: 600; } @media (max-width: 640px) { .shell-footer { padding: 1rem 1rem 1.5rem; } } .eyebrow { font-family: var(--font-sans); text-transform: uppercase; letter-spacing: 0.16em; font-size: 0.6875rem; font-weight: 600; color: var(--muted); } .muted { color: var(--muted); } /* Secondary line inside a row or card — used alongside .muted throughout. */ .small { font-size: 0.8125rem; } /* ============================================================================ App shell / top nav ========================================================================== */ .appbar { position: sticky; top: 0; z-index: 40; background: linear-gradient(180deg, var(--brand-900), var(--brand-800)); color: #f2efe7; border-bottom: 1px solid rgba(0, 0, 0, 0.25); } .appbar-inner { max-width: var(--shell-max); margin: 0 auto; padding: 0 1.75rem; /* min-height, not height: the bar has to grow when the user scales text up. */ min-height: 3.875rem; display: flex; align-items: center; gap: 1.625rem; } @media (max-width: 640px) { .appbar-inner { padding: 0 1rem; gap: 0.875rem; } } .brand { display: flex; align-items: center; gap: 0.75rem; color: #f6f3ec; text-decoration: none; } .brand:hover { text-decoration: none; } .brand-mark { width: 38px; height: 38px; border-radius: 9px; background: #fbf8f0; border: 1px solid rgba(255, 255, 255, 0.18); object-fit: contain; padding: 0.1875rem; box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.2); } .login-brand .brand-mark { width: 46px; height: 46px; border-radius: 10px; } .brand-text { display: flex; flex-direction: column; line-height: 1.05; } .brand-name { font-family: var(--font-display); font-size: 1rem; font-weight: 560; letter-spacing: -0.01em; } .brand-sub { font-size: 0.65625rem; letter-spacing: 0.14em; text-transform: uppercase; color: rgba(242, 239, 231, 0.62); } @media (max-width: 500px) { .brand-sub { display: none; } } .appbar-nav { display: flex; align-items: center; gap: 0.25rem; margin-left: 0.5rem; } .appbar-link { color: rgba(242, 239, 231, 0.78); padding: 0.4375rem 0.75rem; border-radius: 7px; font-size: 0.875rem; font-weight: 500; white-space: nowrap; } .appbar-link:hover { color: #fff; background: rgba(255, 255, 255, 0.08); text-decoration: none; } .appbar-link.active { color: #fff; background: rgba(255, 255, 255, 0.12); } /* Grouped nav entries ("Cobranza", "Admin") */ .appbar-menu { position: relative; } .appbar-menu-trigger { display: inline-flex; align-items: center; gap: 0.375rem; border: 0; background: transparent; font: inherit; font-size: 0.875rem; font-weight: 500; cursor: pointer; } .appbar-caret { width: 0; height: 0; border-left: 4px solid transparent; border-right: 4px solid transparent; border-top: 4.5px solid currentColor; opacity: 0.7; } .appbar-menu-trigger[aria-expanded="true"] { color: #fff; background: rgba(255, 255, 255, 0.12); } .appbar-dropdown { position: absolute; top: calc(100% + 8px); left: 0; min-width: 194px; padding: 0.375rem; display: flex; flex-direction: column; gap: 0.125rem; background: var(--surface); border: 1px solid var(--line); border-radius: 10px; box-shadow: 0 12px 30px rgba(12, 50, 45, 0.22); z-index: 50; } .appbar-dropdown-link { padding: 0.5rem 0.6875rem; border-radius: 7px; font-size: 0.875rem; color: var(--ink); white-space: nowrap; } .appbar-dropdown-link:hover { background: var(--brand-tint); color: var(--brand-800); text-decoration: none; } .appbar-dropdown-link.active { background: var(--brand-tint); color: var(--brand-800); font-weight: 600; box-shadow: inset 2px 0 0 var(--brand-600); } .appbar-dropdown-right { left: auto; right: 0; } .appbar-spacer { flex: 1; } /* Text-size control */ .appbar-scale-trigger { display: inline-flex; align-items: baseline; justify-content: center; min-width: 2.25rem; padding: 0.3125rem 0.5rem; border: 1px solid rgba(255, 255, 255, 0.22); border-radius: 0.5rem; background: rgba(255, 255, 255, 0.06); color: rgba(242, 239, 231, 0.85); font-family: var(--font-sans); font-size: 0.75rem; font-weight: 600; line-height: 1; cursor: pointer; } .appbar-scale-trigger:hover, .appbar-scale-trigger[aria-expanded="true"] { background: rgba(255, 255, 255, 0.14); color: #fff; } .appbar-scale-big { font-size: 1.25rem; } .scale-option { display: flex; align-items: baseline; gap: 0.625rem; width: 100%; border: 0; background: transparent; font-family: var(--font-sans); text-align: left; cursor: pointer; } .scale-option > span:first-child { width: 1.5rem; flex: none; font-weight: 700; line-height: 1; } .scale-option-label { font-size: 0.875rem; } .scale-inline { display: flex; flex-direction: column; gap: 0.375rem; margin-top: 0.75rem; padding-top: 0.75rem; border-top: 1px solid rgba(255, 255, 255, 0.1); } .scale-inline-options { display: flex; align-items: baseline; gap: 0.375rem; padding: 0 0.75rem; } .scale-chip { min-width: 2.75rem; padding: 0.5rem 0.375rem; border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 0.5rem; background: rgba(255, 255, 255, 0.06); color: rgba(242, 239, 231, 0.82); font-family: var(--font-sans); font-weight: 700; line-height: 1; cursor: pointer; } .scale-chip.active { background: rgba(255, 255, 255, 0.18); border-color: rgba(255, 255, 255, 0.4); color: #fff; } /* Mobile menu button + drawer */ .appbar-burger { display: none; width: 38px; height: 38px; padding: 0; border: 1px solid rgba(255, 255, 255, 0.22); border-radius: 9px; background: rgba(255, 255, 255, 0.06); cursor: pointer; place-items: center; } .burger-icon { position: relative; } .burger-icon, .burger-icon::before, .burger-icon::after { display: block; width: 17px; height: 1.8px; border-radius: 2px; background: #f2efe7; transition: transform 0.16s ease, opacity 0.16s ease; } .burger-icon::before, .burger-icon::after { content: ""; position: absolute; } .burger-icon::before { transform: translateY(-5.5px); } .burger-icon::after { transform: translateY(5.5px); } .burger-icon.open { background: transparent; } .burger-icon.open::before { transform: rotate(45deg); } .burger-icon.open::after { transform: rotate(-45deg); } .appbar-drawer { display: none; flex-direction: column; gap: 0.125rem; padding: 0.5rem 1rem 1rem; border-top: 1px solid rgba(255, 255, 255, 0.1); } .appbar-drawer-group { display: flex; flex-direction: column; gap: 0.125rem; margin-top: 0.5rem; } .appbar-drawer-heading { padding: 0.375rem 0.75rem 0.125rem; font-size: 0.65625rem; letter-spacing: 0.14em; text-transform: uppercase; color: rgba(242, 239, 231, 0.45); } .appbar-drawer-link { padding: 0.625rem 0.75rem; border-radius: 8px; font-size: 0.9375rem; color: rgba(242, 239, 231, 0.82); } .appbar-drawer-link:hover { background: rgba(255, 255, 255, 0.08); color: #fff; text-decoration: none; } .appbar-drawer-link.active { background: rgba(255, 255, 255, 0.13); color: #fff; font-weight: 600; } .appbar-drawer-user { margin-top: 0.75rem; padding: 0.625rem 0.75rem 0; border-top: 1px solid rgba(255, 255, 255, 0.1); font-size: 0.78125rem; color: rgba(242, 239, 231, 0.55); } @media (max-width: 980px) { .appbar-nav { display: none; } .appbar-burger { display: grid; } .appbar-drawer { display: flex; } } .appbar-user { display: flex; align-items: center; gap: 0.75rem; font-size: 0.8125rem; color: rgba(242, 239, 231, 0.7); } .appbar-user-name { display: inline-flex; flex-direction: column; line-height: 1.2; } .appbar-user-role { font-size: 0.6875rem; color: rgba(242, 239, 231, 0.45); } /* Below the drawer breakpoint the drawer carries the user's name/role. */ @media (max-width: 980px) { .appbar-user .appbar-user-name { display: none; } } /* ============================================================================ Admin form grid (users, and future CRUD forms) ========================================================================== */ .form-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 1rem; } .form-actions { display: flex; gap: 0.625rem; margin-top: 1.125rem; flex-wrap: wrap; } .row-actions { display: flex; gap: 0.5rem; align-items: center; justify-content: flex-end; } .detail-actionbar { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; flex-wrap: wrap; margin-bottom: 0.5rem; } .inline-form-note { font-size: 0.8125rem; color: var(--muted, #6b7280); margin: 0.25rem 0 0.875rem; } .child-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 0.625rem; } .child-editor { border-top: 1px solid rgba(0, 0, 0, 0.08); margin-top: 0.75rem; padding-top: 0.875rem; } .picker { position: relative; } .picker-selected { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; padding: 0.5rem 0.75rem; border: 1px solid rgba(0, 0, 0, 0.15); border-radius: 8px; } .picker-list { position: absolute; z-index: 20; top: 100%; left: 0; right: 0; margin: 0.25rem 0 0; padding: 0.25rem; list-style: none; background: var(--card-bg, #fff); border: 1px solid rgba(0, 0, 0, 0.15); border-radius: 8px; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12); max-height: 280px; overflow-y: auto; } .picker-item { display: block; width: 100%; text-align: left; padding: 0.5rem 0.625rem; border: 0; background: transparent; border-radius: 6px; cursor: pointer; font: inherit; } .picker-item:hover { background: rgba(0, 0, 0, 0.05); } /* ============================================================================ Buttons ========================================================================== */ .btn { display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem; border-radius: var(--radius-sm); border: 1px solid transparent; padding: 0.5625rem 1rem; font-size: 0.875rem; font-weight: 600; line-height: 1; transition: transform 0.12s var(--ease-out-quart), background 0.15s, box-shadow 0.15s, border-color 0.15s; } .btn:active { transform: translateY(1px); } .btn-primary { background: var(--accent); color: #fff; box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08), inset 0 1px 0 rgba(255, 255, 255, 0.15); } .btn-primary:hover { background: var(--accent-600); text-decoration: none; } .btn-ghost { background: transparent; color: var(--ink-soft); border-color: var(--line-strong); } .btn-ghost:hover { background: var(--surface-2); color: var(--ink); border-color: var(--brand-600); text-decoration: none; } /* Dark appbar keeps the light-on-dark ghost button. */ .appbar .btn-ghost { color: rgba(242, 239, 231, 0.85); border-color: rgba(255, 255, 255, 0.22); } .appbar .btn-ghost:hover { background: rgba(255, 255, 255, 0.1); color: #fff; border-color: rgba(255, 255, 255, 0.35); } .btn-outline { background: var(--surface); color: var(--ink-soft); border-color: var(--line-strong); } .btn-outline:hover { border-color: var(--brand-600); color: var(--brand-700); text-decoration: none; } .btn:disabled { opacity: 0.55; cursor: not-allowed; transform: none; } /* ============================================================================ Cards / panels ========================================================================== */ .card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-lg); box-shadow: var(--shadow-sm); } /* ============================================================================ Badges / chips ========================================================================== */ .badge { display: inline-flex; align-items: center; gap: 0.375rem; padding: 0.1875rem 0.5625rem; border-radius: 999px; font-size: 0.75rem; font-weight: 600; letter-spacing: 0.01em; line-height: 1.4; border: 1px solid transparent; white-space: nowrap; } .badge .dot { width: 7px; height: 7px; border-radius: 50%; } .badge-servicios { background: var(--servicios-tint); color: var(--servicios-ink); border-color: rgba(154, 106, 18, 0.28); } .badge-servicios .dot { background: var(--servicios); } .badge-seguros { background: var(--seguros-tint); color: var(--seguros-ink); border-color: rgba(15, 111, 104, 0.28); } .badge-seguros .dot { background: var(--seguros); } .badge-fideicomiso { background: var(--fideicomiso-tint); color: var(--fideicomiso-ink); border-color: rgba(109, 63, 96, 0.28); } .badge-fideicomiso .dot { background: var(--fideicomiso); } .badge-neutral { background: var(--paper-2); color: var(--muted); border-color: var(--line-strong); } .badge-positive { background: var(--positive-tint); color: var(--positive); border-color: rgba(47, 109, 60, 0.25); } .badge-negative { background: var(--negative-tint); color: var(--negative); border-color: rgba(162, 58, 44, 0.25); } .badge-count { font-family: var(--font-mono); font-feature-settings: "tnum" 1; } /* ============================================================================ Utility animation ========================================================================== */ @keyframes rise { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } .rise { animation: rise 0.5s var(--ease-out-expo) both; } @keyframes spin { to { transform: rotate(360deg); } } .spinner { width: 18px; height: 18px; border-radius: 50%; border: 2.5px solid currentColor; border-top-color: transparent; animation: spin 0.7s linear infinite; display: inline-block; } /* Upload progress (Operaciones ingest) */ .upload-progress { display: flex; flex-direction: column; gap: 6px; padding: 4px 0 8px; } .progress-track { position: relative; overflow: hidden; height: 8px; border-radius: 999px; background: var(--paper-2); } .progress-fill { height: 100%; border-radius: 999px; background: var(--brand-500); transition: width 0.2s linear; } .progress-indeterminate .progress-fill { width: 40% !important; animation: progress-slide 1.2s var(--ease-out-quart) infinite; } @keyframes progress-slide { 0% { transform: translateX(-100%); } 100% { transform: translateX(250%); } } .upload-progress-stats { display: flex; flex-wrap: wrap; gap: 12px; font-size: 12px; color: var(--muted); } @keyframes shimmer { 0% { background-position: -420px 0; } 100% { background-position: 420px 0; } } .skeleton { background: linear-gradient( 90deg, var(--paper-2) 25%, #e8e1d2 37%, var(--paper-2) 63% ); background-size: 840px 100%; animation: shimmer 1.4s linear infinite; border-radius: 6px; } @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; transition-duration: 0.001ms !important; } } /* ============================================================================ Form fields (shared) ========================================================================== */ .field { display: block; margin-bottom: 1.125rem; } .field-label { display: block; font-size: 0.8125rem; font-weight: 600; color: var(--ink-soft); margin-bottom: 0.4375rem; } .input { width: 100%; font-family: inherit; font-size: 0.9375rem; color: var(--ink); background: var(--surface); border: 1px solid var(--line-strong); border-radius: var(--radius-sm); padding: 0.6875rem 0.8125rem; transition: border-color 0.15s, box-shadow 0.15s; } .input::placeholder { color: var(--muted-2); } .input:focus { outline: none; border-color: var(--brand-600); box-shadow: 0 0 0 3px var(--brand-tint); } /* ============================================================================ Login screen — split brand / form layout ========================================================================== */ .login-wrap { min-height: 100vh; display: grid; grid-template-columns: 1.05fr 1fr; } @media (max-width: 860px) { .login-wrap { grid-template-columns: 1fr; } } .login-aside { position: relative; background: linear-gradient(155deg, var(--brand-900) 0%, var(--brand-700) 62%, #17544a 100%); color: #f2efe7; padding: 2.75rem 3.25rem; display: flex; flex-direction: column; justify-content: space-between; overflow: hidden; } .login-aside::after { /* faint concentric coastal arcs */ content: ""; position: absolute; right: -180px; bottom: -180px; width: 560px; height: 560px; border-radius: 50%; border: 1px solid rgba(255, 255, 255, 0.08); box-shadow: 0 0 0 60px rgba(255, 255, 255, 0.04), 0 0 0 130px rgba(255, 255, 255, 0.03); pointer-events: none; } @media (max-width: 860px) { .login-aside { padding: 2rem 1.75rem 2.5rem; } .login-aside-mid { margin: 1.875rem 0; } } .login-brand { display: flex; align-items: center; gap: 0.8125rem; position: relative; z-index: 1; } .login-aside-mid { position: relative; z-index: 1; max-width: 460px; } .login-headline { font-family: var(--font-display); color: #fbf8f0; font-size: clamp(30px, 4.6vw, 46px); font-weight: 500; line-height: 1.08; margin: 0.875rem 0 1.25rem; letter-spacing: -0.015em; } .login-headline em { font-style: italic; color: #ecc98d; } .login-lede { font-size: 1rem; line-height: 1.6; color: rgba(242, 239, 231, 0.82); max-width: 420px; } .login-aside-foot { position: relative; z-index: 1; display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; } .login-lob { display: flex; gap: 0.5rem; } .login-foot-note { font-size: 0.78125rem; color: rgba(242, 239, 231, 0.55); } .login-form-panel { display: grid; place-items: center; padding: 2.5rem 1.75rem; background: var(--paper); } .login-form-inner { width: 100%; max-width: 380px; } .login-form-title { font-size: 1.875rem; margin-top: 0.25rem; } .login-error { background: var(--negative-tint); color: var(--negative); border: 1px solid rgba(162, 58, 44, 0.28); border-radius: var(--radius-sm); padding: 0.625rem 0.8125rem; font-size: 0.84375rem; font-weight: 500; margin-bottom: 1.125rem; } .login-submit { width: 100%; padding: 0.75rem 1rem; font-size: 0.9375rem; } /* ============================================================================ Page heading + stats (customer list) ========================================================================== */ .page-head { margin-bottom: 1.625rem; } .page-title { font-size: clamp(28px, 4vw, 38px); font-weight: 500; margin: 0.25rem 0 0; } .stat-strip { display: grid; grid-template-columns: repeat(6, 1fr); gap: 0.0625rem; background: var(--line); border: 1px solid var(--line); border-radius: var(--radius-lg); overflow: hidden; margin-top: 1.375rem; } @media (max-width: 900px) { .stat-strip { grid-template-columns: repeat(3, 1fr); } } @media (max-width: 520px) { .stat-strip { grid-template-columns: repeat(2, 1fr); } } .stat-cell { background: var(--surface); padding: 0.9375rem 1rem 0.875rem; } .stat-cell.accent { background: var(--brand-tint); } .stat-value { font-family: var(--font-display); font-size: 1.5625rem; font-weight: 560; color: var(--ink); font-feature-settings: "tnum" 1; letter-spacing: -0.01em; } .stat-cell.accent .stat-value { color: var(--brand-700); } .stat-label { font-size: 0.71875rem; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 0.1875rem; font-weight: 600; } /* ============================================================================ Search + filter toolbar ========================================================================== */ .toolbar { display: flex; gap: 0.875rem; align-items: center; flex-wrap: wrap; margin: 1.625rem 0 1.125rem; } .search-box { position: relative; flex: 1 1 320px; } .search-box .search-icon { position: absolute; left: 13px; top: 50%; transform: translateY(-50%); color: var(--muted-2); font-size: 1rem; pointer-events: none; } .search-input { width: 100%; padding-left: 2.375rem; } .seg { display: inline-flex; background: var(--paper-2); border: 1px solid var(--line-strong); border-radius: 999px; padding: 0.1875rem; gap: 0.125rem; } .seg-btn { border: none; background: transparent; color: var(--muted); font-size: 0.8125rem; font-weight: 600; padding: 0.4375rem 0.9375rem; border-radius: 999px; transition: color 0.15s, background 0.15s; white-space: nowrap; } .seg-btn:hover { color: var(--ink); } .seg-btn.active { background: var(--surface); color: var(--brand-700); box-shadow: var(--shadow-sm); } @media (max-width: 560px) { .seg { width: 100%; justify-content: space-between; } .seg-btn { flex: 1; padding: 0.5rem 0.375rem; } } .result-meta { font-size: 0.8125rem; color: var(--muted); margin-bottom: 0.75rem; } /* ============================================================================ Customer list (rows) ========================================================================== */ .cust-list { display: flex; flex-direction: column; gap: 0.625rem; } .cust-row { display: grid; grid-template-columns: 1fr auto; gap: 1rem; align-items: center; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: 0.9375rem 1.125rem; text-decoration: none; color: inherit; transition: transform 0.14s var(--ease-out-quart), box-shadow 0.14s, border-color 0.14s; } .cust-row:hover { text-decoration: none; transform: translateY(-1px); box-shadow: var(--shadow); border-color: var(--line-strong); } .cust-main { min-width: 0; } .cust-name { font-family: var(--font-display); font-size: 1.0625rem; font-weight: 560; color: var(--ink); letter-spacing: -0.01em; display: flex; align-items: center; gap: 0.625rem; } .cust-name .inactive-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--muted-2); flex: none; } /* Legacy record with no name anywhere in the source — reads as absent data, not as a customer actually called "(SIN NOMBRE)". */ .cust-name-missing { color: var(--muted-2); font-style: italic; font-weight: 400; } /* Name reconstructed from a secondary legacy table, so staff can tell it apart from a name that was really on the customer record. */ .name-source { font-family: var(--font-sans); font-size: 0.625rem; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted-2); border: 1px solid var(--line-strong); border-radius: 4px; padding: 0.125rem 0.375rem; white-space: nowrap; cursor: help; } .cust-sub { display: flex; flex-wrap: wrap; gap: 0.375rem 1rem; margin-top: 0.3125rem; font-size: 0.8125rem; color: var(--muted); } .cust-sub .sep { color: var(--line-strong); } .cust-side { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; justify-content: flex-end; } @media (max-width: 620px) { .cust-row { grid-template-columns: 1fr; } .cust-side { justify-content: flex-start; } } /* ============================================================================ Pagination ========================================================================== */ .pager { display: flex; align-items: center; justify-content: center; gap: 0.75rem; margin-top: 1.625rem; } .pager-info { font-size: 0.8125rem; color: var(--muted); min-width: 130px; text-align: center; } /* ============================================================================ Empty / error / loading states ========================================================================== */ .state-box { text-align: center; padding: 3.75rem 1.5rem; color: var(--muted); } .state-box h3 { color: var(--ink-soft); font-size: 1.25rem; margin-bottom: 0.375rem; } .state-glyph { font-size: 2.125rem; opacity: 0.5; margin-bottom: 0.625rem; } .state-error { background: var(--negative-tint); border: 1px solid rgba(162, 58, 44, 0.25); color: var(--negative); border-radius: var(--radius); padding: 1rem 1.125rem; font-size: 0.875rem; } .skel-row { height: 74px; border-radius: var(--radius); } /* ============================================================================ Customer detail — hero ========================================================================== */ .back-link { display: inline-flex; align-items: center; gap: 0.375rem; font-size: 0.84375rem; font-weight: 600; color: var(--muted); margin-bottom: 1.125rem; } .back-link:hover { color: var(--brand-700); text-decoration: none; } .detail-hero { background: linear-gradient(150deg, var(--brand-900), var(--brand-700) 88%); color: #f2efe7; border-radius: var(--radius-lg); padding: 1.625rem 1.75rem; position: relative; overflow: hidden; box-shadow: var(--shadow); } .detail-hero::after { content: ""; position: absolute; right: -120px; top: -140px; width: 340px; height: 340px; border-radius: 50%; border: 1px solid rgba(255, 255, 255, 0.08); box-shadow: 0 0 0 44px rgba(255, 255, 255, 0.04); pointer-events: none; } .hero-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 1.125rem; flex-wrap: wrap; position: relative; z-index: 1; } .hero-name { font-family: var(--font-display); font-weight: 500; color: #fbf8f0; font-size: clamp(24px, 3.4vw, 34px); letter-spacing: -0.015em; line-height: 1.1; } .hero-name-missing { font-style: italic; color: rgba(251, 248, 240, 0.55); } .hero-provenance { font-size: 0.78125rem; color: rgba(242, 239, 231, 0.62); margin-top: 0.5rem; font-family: var(--font-mono); } .hero-badges { display: flex; gap: 0.5rem; flex-wrap: wrap; align-items: center; } .badge-on-dark { background: rgba(255, 255, 255, 0.12); color: #f2efe7; border-color: rgba(255, 255, 255, 0.2); } .hero-facts { position: relative; z-index: 1; display: flex; flex-wrap: wrap; gap: 1.625rem; margin-top: 1.375rem; padding-top: 1.125rem; border-top: 1px solid rgba(255, 255, 255, 0.12); } .hero-fact-label { font-size: 0.65625rem; text-transform: uppercase; letter-spacing: 0.1em; color: rgba(242, 239, 231, 0.55); font-weight: 600; } .hero-fact-value { font-size: 0.9375rem; color: #f6f3ec; margin-top: 0.125rem; font-weight: 500; } /* ============================================================================ Section scaffolding ========================================================================== */ .section { margin-top: 2.125rem; } .section-head { display: flex; align-items: baseline; gap: 0.75rem; margin-bottom: 1rem; } .section-rule { width: 4px; align-self: stretch; border-radius: 3px; min-height: 1.375rem; } .section-rule.servicios { background: var(--servicios); } .section-rule.seguros { background: var(--seguros); } .section-rule.cuenta { background: var(--accent); } .section-rule.datos { background: var(--brand-600); } .section-rule.docs { background: var(--muted-2); } .section-title { font-size: 1.375rem; font-weight: 560; } .section-count { font-size: 0.8125rem; color: var(--muted); font-weight: 600; font-family: var(--font-mono); } /* ---- key/value grid (datos del cliente) ---- */ .kv-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1.125rem 1.5rem; padding: 1.375rem 1.5rem; } .kv-label { font-size: 0.6875rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); font-weight: 600; margin-bottom: 0.1875rem; } .kv-value { font-size: 0.90625rem; color: var(--ink); } .kv-value.mono { font-size: 0.875rem; } .kv-block { grid-column: 1 / -1; border-top: 1px dashed var(--line-strong); padding-top: 1rem; margin-top: -0.125rem; } /* ---- property cards ---- */ .prop-card { padding: 1.25rem 1.375rem; } .prop-card + .prop-card { border-top: 1px solid var(--line); } .prop-addr { font-family: var(--font-display); font-size: 1.0625rem; font-weight: 560; color: var(--ink); } .prop-meta { font-size: 0.8125rem; color: var(--muted); margin-top: 0.1875rem; display: flex; gap: 0.875rem; flex-wrap: wrap; } .svc-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 0.625rem; margin-top: 1rem; } .svc-item { border: 1px solid var(--line); border-left: 3px solid var(--servicios); border-radius: var(--radius-sm); background: var(--surface-2); padding: 0.6875rem 0.8125rem; } .svc-item.inactive { opacity: 0.62; border-left-color: var(--muted-2); } .svc-head { display: flex; align-items: center; gap: 0.5rem; justify-content: space-between; } .svc-kind { font-weight: 700; font-size: 0.84375rem; color: var(--servicios-ink); display: flex; align-items: center; gap: 0.4375rem; } .svc-glyph { font-size: 0.875rem; } .svc-detail { margin-top: 0.4375rem; font-size: 0.75rem; color: var(--muted); display: flex; flex-direction: column; gap: 0.125rem; } .svc-detail .mono { color: var(--ink-soft); } .trust-box { margin-top: 1rem; border: 1px solid var(--fideicomiso-tint); background: linear-gradient(0deg, var(--fideicomiso-tint), transparent 140%); border-left: 3px solid var(--fideicomiso); border-radius: var(--radius-sm); padding: 0.8125rem 0.9375rem; } .trust-title { font-size: 0.78125rem; font-weight: 700; color: var(--fideicomiso-ink); text-transform: uppercase; letter-spacing: 0.04em; margin-bottom: 0.5rem; } .trust-facts { display: flex; flex-wrap: wrap; gap: 0.5rem 1.375rem; font-size: 0.8125rem; } /* ---- policy cards ---- */ .policy-card { padding: 1.25rem 1.375rem; } .policy-card + .policy-card { border-top: 1px solid var(--line); } .policy-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem; flex-wrap: wrap; } .policy-num { font-family: var(--font-mono); font-size: 1.125rem; font-weight: 600; color: var(--seguros-ink); letter-spacing: -0.01em; } .policy-type-row { display: flex; align-items: center; gap: 0.5rem; margin-top: 0.3125rem; font-size: 0.8125rem; color: var(--muted); flex-wrap: wrap; } .policy-figures { text-align: right; } .policy-total { font-family: var(--font-display); font-size: 1.375rem; font-weight: 560; color: var(--ink); font-feature-settings: "tnum" 1; } .policy-total-label { font-size: 0.6875rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); } .policy-body { margin-top: 1rem; display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 1rem; } .subpanel { background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 0.75rem 0.875rem; } .subpanel-title { font-size: 0.6875rem; text-transform: uppercase; letter-spacing: 0.07em; color: var(--muted); font-weight: 700; margin-bottom: 0.5625rem; display: flex; justify-content: space-between; } .pay-row { display: flex; align-items: center; justify-content: space-between; gap: 0.625rem; font-size: 0.8125rem; padding: 0.3125rem 0; border-bottom: 1px dashed var(--line); } .pay-row:last-child { border-bottom: none; } .pay-seq { width: 22px; height: 22px; border-radius: 50%; background: var(--seguros-tint); color: var(--seguros-ink); font-size: 0.6875rem; font-weight: 700; display: grid; place-items: center; flex: none; } .mini-list { font-size: 0.84375rem; color: var(--ink-soft); display: flex; flex-direction: column; gap: 0.3125rem; } .mini-list .mini-sub { font-size: 0.75rem; color: var(--muted); } /* ============================================================================ Estado de cuenta ========================================================================== */ .summary-grid { display: grid; /* Min track holds a 7-figure balance (e.g. TRASPASOS PAYPAL's -$7,028,533.44) in full — auto-fill packs fixed-width tracks, so a single-currency card never widens on its own and the min is what has to fit the number. */ grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 0.75rem; margin-bottom: 1.125rem; } .summary-card { border: 1px solid var(--line); border-radius: var(--radius); padding: 0.9375rem 1rem; background: var(--surface); border-top: 3px solid var(--muted-2); } .summary-card.UTILITY { border-top-color: var(--servicios); } .summary-card.INSURANCE { border-top-color: var(--seguros); } .summary-card.TRUST { border-top-color: var(--fideicomiso); } .summary-domain { display: flex; align-items: center; gap: 0.4375rem; font-size: 0.75rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted); } .summary-total { font-family: var(--font-display); font-size: 1.375rem; font-weight: 560; margin-top: 0.5rem; font-feature-settings: "tnum" 1; color: var(--ink); /* Never truncate a balance — a clipped money figure reads as a wrong number. The track width above is what keeps it inside the card. */ } .summary-count { font-size: 0.75rem; color: var(--muted); margin-top: 0.125rem; } .tx-table { width: 100%; border-collapse: collapse; font-size: 0.84375rem; } .tx-table th { text-align: left; font-size: 0.65625rem; text-transform: uppercase; letter-spacing: 0.07em; color: var(--muted); font-weight: 700; padding: 0 0.75rem 0.625rem; border-bottom: 1px solid var(--line); } .tx-table th.num, .tx-table td.num { text-align: right; } .tx-table td { padding: 0.6875rem 0.75rem; border-bottom: 1px solid var(--line); vertical-align: top; } .tx-table tr:last-child td { border-bottom: none; } .tx-table tr:hover td { background: var(--surface-2); } /* Drill-down rows (the chequera's yearly summary) read as pressable. */ .tx-table tr.selected td { background: var(--surface-2); box-shadow: inset 2px 0 0 var(--brand-600); } .tx-domain-cell { white-space: nowrap; } .tx-dot { display: inline-block; width: 8px; height: 8px; border-radius: 2px; margin-right: 0.4375rem; vertical-align: middle; } .tx-dot.UTILITY { background: var(--servicios); } .tx-dot.INSURANCE { background: var(--seguros); } .tx-dot.TRUST { background: var(--fideicomiso); } .tx-amount { font-family: var(--font-mono); font-weight: 600; font-feature-settings: "tnum" 1; white-space: nowrap; } .tx-amount.neg { color: var(--negative); } .tx-amount.pos { color: var(--positive); } .tx-cur { font-size: 0.6875rem; color: var(--muted); font-weight: 500; } .tx-concept { color: var(--ink-soft); } .tx-ref { font-family: var(--font-mono); font-size: 0.78125rem; color: var(--muted); } .tx-scroll { overflow-x: auto; } /* ---- documents ---- */ .doc-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 0.625rem; padding: 1.25rem 1.375rem; } .doc-item { display: flex; align-items: center; gap: 0.6875rem; border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 0.6875rem 0.8125rem; background: var(--surface-2); } .doc-icon { width: 32px; height: 32px; border-radius: 7px; background: var(--paper-2); display: grid; place-items: center; font-size: 0.9375rem; flex: none; color: var(--brand-700); } .doc-type { font-size: 0.84375rem; font-weight: 600; color: var(--ink); } .doc-key { font-size: 0.6875rem; color: var(--muted-2); font-family: var(--font-mono); word-break: break-all; } .empty-inline { padding: 1.375rem 1.5rem; color: var(--muted); font-size: 0.875rem; font-style: italic; } .section-note { font-size: 0.75rem; color: var(--muted); margin-top: 0.625rem; } /* ============================================================================ Policies — vigencia badges ========================================================================== */ .badge.status-active { background: var(--positive-tint); color: var(--positive); border-color: rgba(47, 109, 60, 0.25); } .badge.status-expiring { background: var(--accent-tint); color: var(--accent-600); border-color: rgba(191, 90, 52, 0.28); } .badge.status-expired { background: var(--negative-tint); color: var(--negative); border-color: rgba(162, 58, 44, 0.25); } .badge.status-undated { background: var(--paper-2); color: var(--muted); border-color: var(--line-strong); } /* ============================================================================ Policies — header strips ========================================================================== */ /* Stat cells double as vigencia filters on /polizas. */ .stat-cell-btn { display: block; width: 100%; text-align: left; border: none; cursor: pointer; font: inherit; transition: background 0.15s; } .stat-cell-btn:hover { background: var(--surface-2); } .stat-cell-btn.accent:hover { background: #d7e6e1; } .stat-cell-btn.selected { box-shadow: inset 0 -3px 0 var(--brand-600); } .premium-strip { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; margin-top: 0.875rem; padding: 0 0.125rem; } .premium-caption { font-size: 0.71875rem; text-transform: uppercase; letter-spacing: 0.05em; font-weight: 600; color: var(--muted); } .premium-chip { display: inline-flex; align-items: baseline; gap: 0.5rem; } .premium-chip strong { font-family: var(--font-mono); font-feature-settings: "tnum" 1; font-size: 0.9375rem; color: var(--brand-700); } .premium-chip-sub { font-size: 0.75rem; color: var(--muted); } /* ============================================================================ Policies — secondary filter row ========================================================================== */ .filter-row { display: flex; gap: 0.875rem; align-items: flex-end; flex-wrap: wrap; margin-bottom: 1.125rem; } .filter-field { display: flex; flex-direction: column; gap: 0.3125rem; flex: 1 1 210px; min-width: 0; } .filter-label { font-size: 0.71875rem; text-transform: uppercase; letter-spacing: 0.05em; font-weight: 600; color: var(--muted); } .select { appearance: none; cursor: pointer; padding-right: 2.125rem; background-image: linear-gradient(45deg, transparent 50%, var(--muted) 50%), linear-gradient(135deg, var(--muted) 50%, transparent 50%); background-position: calc(100% - 18px) 55%, calc(100% - 13px) 55%; background-size: 5px 5px, 5px 5px; background-repeat: no-repeat; } .filter-clear { flex: 0 0 auto; height: 40px; } /* ============================================================================ Policies — list rows ========================================================================== */ .pol-row .cust-name { flex-wrap: wrap; gap: 0.5625rem; } .pol-number { font-size: 0.9375rem; font-weight: 600; letter-spacing: -0.01em; } .pol-side { text-align: right; display: flex; flex-direction: column; align-items: flex-end; gap: 0.1875rem; flex: 0 0 auto; } .pol-premium { font-family: var(--font-mono); font-feature-settings: "tnum" 1; font-size: 0.9375rem; font-weight: 600; color: var(--ink); } .pol-dates { font-size: 0.75rem; color: var(--muted); white-space: nowrap; } .pol-phrase { font-size: 0.71875rem; font-weight: 600; } .pol-phrase.expiring { color: var(--accent-600); } .pol-phrase.active { color: var(--positive); } @media (max-width: 620px) { .pol-side { align-items: flex-start; text-align: left; margin-top: 0.5rem; } } /* ============================================================================ Policy detail — owner card, linked properties, vehicles ========================================================================== */ .owner-link { display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: 1.125rem 1.375rem; color: inherit; text-decoration: none; border-radius: var(--radius-lg); transition: background 0.15s; } .owner-link:hover { background: var(--surface-2); } .owner-name { font-family: var(--font-display); font-size: 1.1875rem; font-weight: 560; margin-bottom: 0.1875rem; } .owner-cta { font-size: 0.8125rem; font-weight: 600; color: var(--brand-600); white-space: nowrap; } .linked-props { border-top: 1px solid var(--line); padding: 1rem 1.375rem 1.125rem; } .linked-prop { font-size: 0.875rem; margin-top: 0.25rem; } .veh-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 0.75rem; padding: 1rem; } .veh-card { background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--radius); padding: 0.8125rem 0.9375rem; } .veh-title { font-weight: 600; font-size: 0.90625rem; margin-bottom: 0.375rem; } .veh-facts { display: flex; flex-direction: column; gap: 0.1875rem; font-size: 0.78125rem; color: var(--muted); } /* Policy number on the customer detail card links through to /polizas/[id]. */ .policy-num-link { color: inherit; text-decoration: none; transition: color 0.15s; } .policy-num-link:hover { color: var(--brand-600); } /* ============================================================================ Utilities — service mix strip (doubles as the service-kind filter) ========================================================================== */ .mix-strip { display: flex; align-items: center; gap: 0.625rem; flex-wrap: wrap; margin-top: 0.875rem; padding: 0 0.125rem; } .mix-chip { display: inline-flex; align-items: center; gap: 0.5rem; padding: 0.375rem 0.6875rem; background: var(--surface-2); border: 1px solid var(--line); border-radius: 999px; cursor: pointer; font: inherit; color: inherit; transition: border-color 0.15s, background 0.15s; } .mix-chip:hover { border-color: var(--brand-600); } .mix-chip.selected { border-color: var(--brand-600); box-shadow: inset 0 0 0 1px var(--brand-600); } .mix-glyph { font-size: 0.8125rem; color: var(--brand-600); } .mix-body { display: inline-flex; align-items: baseline; gap: 0.375rem; } .mix-body strong { font-family: var(--font-mono); font-feature-settings: "tnum" 1; font-size: 0.875rem; color: var(--brand-700); } .mix-label { font-size: 0.78125rem; color: var(--muted); } .mix-inactive { font-size: 0.6875rem; color: var(--muted); border-left: 1px solid var(--line); padding-left: 0.5rem; } /* ============================================================================ Utilities — property list rows ========================================================================== */ .prop-row .cust-name { flex-wrap: wrap; gap: 0.5625rem; } .prop-side { text-align: right; display: flex; flex-direction: column; align-items: flex-end; gap: 0.3125rem; flex: 0 0 auto; } .svc-chips { display: flex; gap: 0.3125rem; flex-wrap: wrap; justify-content: flex-end; } .svc-chip { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; border-radius: 7px; background: var(--surface-2); border: 1px solid var(--line); font-size: 0.75rem; color: var(--brand-600); } .svc-chip.inactive { opacity: 0.45; } @media (max-width: 620px) { .prop-side { align-items: flex-start; text-align: left; margin-top: 0.5rem; } .svc-chips { justify-content: flex-start; } } /* Sibling properties on the property detail are navigable. */ .linked-prop.link { display: block; color: inherit; text-decoration: none; transition: color 0.15s; } .linked-prop.link:hover { color: var(--brand-600); } .inline-link { color: var(--brand-600); text-decoration: none; font-weight: 600; } .inline-link:hover { text-decoration: underline; } /* Visually hidden, still read by screen readers (service kind chips). */ .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -0.0625rem; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; } /* ================================================================ Estado de cuenta (billing / statements) — plan step 6 ================================================================ */ /* A balance is signed: negative means the customer owes the office, positive means they hold a credit. `flat` is a real state (settled to zero), not a fallback, so it gets its own muted treatment rather than inheriting either. */ .bal-amount { font-family: var(--font-mono); font-weight: 700; font-feature-settings: "tnum" 1; white-space: nowrap; } .bal-amount.owing { color: var(--negative); } .bal-amount.credit { color: var(--positive); } .bal-amount.flat { color: var(--muted); } .bal-running { font-family: var(--font-mono); font-size: 0.78125rem; font-feature-settings: "tnum" 1; white-space: nowrap; color: var(--ink-soft); } .bal-running.owing { color: var(--negative); } .bal-running.credit { color: var(--positive); } .bal-row .bal-side { text-align: right; display: flex; flex-direction: column; gap: 0.125rem; align-items: flex-end; min-width: 160px; } .bal-side .bal-amount { font-size: 1rem; } .bal-phrase { font-size: 0.6875rem; font-weight: 600; letter-spacing: 0.03em; text-transform: uppercase; } .bal-phrase.owing { color: var(--negative); } .bal-phrase.credit { color: var(--positive); } .bal-phrase.flat { color: var(--muted); } /* The customer's other-currency balance, shown so a peso figure is never mistaken for the whole picture. */ .bal-other { font-size: 0.71875rem; color: var(--muted); font-family: var(--font-mono); } @media (max-width: 640px) { .bal-row .bal-side { align-items: flex-start; text-align: left; min-width: 0; } } /* Currency cards on the statement double as the movement-table currency switch, so they are buttons, not divs. */ .bal-card { text-align: left; cursor: pointer; font: inherit; border: 1px solid var(--line); transition: border-color 0.15s ease, transform 0.15s ease; } .bal-card:hover { transform: translateY(-1px); } .bal-card.selected { border-color: var(--brand-600); box-shadow: 0 0 0 1px var(--brand-600); } .bal-breakdown { display: grid; grid-template-columns: auto 1fr; gap: 0.0625rem 0.5rem; margin-top: 0.5rem; font-size: 0.75rem; align-items: baseline; } .bal-breakdown-label { color: var(--muted); font-size: 0.71875rem; } /* Ledger-wide charge/credit totals in the page header. */ .ledger-chip { display: flex; align-items: center; gap: 0.875rem; padding: 0.5rem 0.875rem; border: 1px solid var(--line); border-radius: 10px; background: var(--surface-2); } .ledger-chip-cur { font-weight: 700; font-size: 0.75rem; letter-spacing: 0.06em; color: var(--muted); } .ledger-chip-figs { display: flex; flex-direction: column; line-height: 1.3; } .ledger-chip-label { font-size: 0.6875rem; color: var(--muted); } /* Totals for the current movement filter — deliberately above the table, so a filtered view can't be read as if it were the whole ledger. */ .filtered-totals { display: flex; flex-wrap: wrap; gap: 0.625rem; margin-bottom: 0.75rem; } .filtered-total { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.875rem; padding: 0.5625rem 0.875rem; border: 1px solid var(--line); border-radius: 10px; background: var(--surface-2); font-size: 0.78125rem; color: var(--muted); } .filtered-total-cur { font-weight: 700; letter-spacing: 0.06em; color: var(--ink-soft); } .filtered-total-net strong { font-family: var(--font-mono); color: var(--ink); } /* Captured-but-unpaid (legacy NOPAGO). Deliberately not the same treatment as a voided row: the movement is real and still pending, it just doesn't count toward the balance until a check resolves it. */ .tx-outstanding { color: var(--warn, #b45309); font-weight: 600; } /* Charges broken out by concept, with a proportional bar. `.card` carries no padding, so the list pads itself — otherwise the total sits on the border. */ .concept-list { display: flex; flex-direction: column; padding: 0.25rem 1rem; } .concept-row { display: grid; grid-template-columns: minmax(150px, 1.2fr) minmax(60px, 2fr) auto; gap: 0.875rem; align-items: center; padding: 0.5625rem 0; border-bottom: 1px solid var(--line); } .concept-row:last-child { border-bottom: none; } .concept-name { font-size: 0.84375rem; font-weight: 600; display: flex; flex-direction: column; } .concept-count { font-size: 0.71875rem; font-weight: 500; color: var(--muted); } .concept-bar { height: 7px; background: var(--surface-2); border-radius: 4px; overflow: hidden; } .concept-bar span { display: block; height: 100%; border-radius: 4px; background: var(--negative); opacity: 0.55; } .concept-total { text-align: right; font-size: 0.8125rem; } @media (max-width: 640px) { .concept-row { grid-template-columns: 1fr auto; } .concept-bar { display: none; } } /* Cross-link out of a detail hero (statement -> customer file). */ .hero-links { margin-top: 1rem; display: flex; gap: 0.625rem; flex-wrap: wrap; position: relative; z-index: 1; } /* --- Admin DB operations (Operaciones) --- */ .btn-danger { background: var(--negative); color: #fff; } .btn-danger:hover { filter: brightness(0.94); text-decoration: none; } .btn-danger:disabled { opacity: 0.5; cursor: not-allowed; } .ops-log { margin: 0.75rem 0 0; padding: 0.75rem 0.875rem; max-height: 320px; overflow: auto; background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--radius-sm); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.75rem; line-height: 1.5; white-space: pre-wrap; word-break: break-word; } .modal-backdrop { position: fixed; inset: 0; background: rgba(0, 0, 0, 0.4); display: grid; place-items: center; padding: 1.25rem; z-index: 50; } /* ============================================================================ Home dashboard (/inicio) ========================================================================== */ .home { display: flex; flex-direction: column; gap: 2.25rem; padding-top: 0.5rem; } .home-last-seen { margin-top: 0.875rem; font-size: 0.8125rem; } .home-section { display: flex; flex-direction: column; gap: 0.875rem; } .section-head { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; flex-wrap: wrap; } .section-title { font-family: var(--font-display); font-size: 1.25rem; font-weight: 560; margin: 0; color: var(--ink); letter-spacing: -0.005em; } .section-sub { font-size: 0.78125rem; color: var(--muted); } /* KPI cards row — 4 across on wide screens, 2 on tablet, 1 on mobile */ .home-section.kpi-row { display: grid; } .home > .home-section:first-of-type { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0.875rem; } @media (max-width: 1080px) { .home > .home-section:first-of-type { grid-template-columns: repeat(2, 1fr); } } @media (max-width: 560px) { .home > .home-section:first-of-type { grid-template-columns: 1fr; } } .kpi-card { display: flex; flex-direction: column; padding: 1.125rem 1.125rem 1rem; text-decoration: none; color: inherit; transition: transform 0.18s var(--ease-out-expo), box-shadow 0.18s; position: relative; } .kpi-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); } .kpi-label { font-size: 0.71875rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); font-weight: 700; } .kpi-primary { font-family: var(--font-display); font-size: 2rem; font-weight: 560; color: var(--ink); margin-top: 0.5rem; font-feature-settings: "tnum" 1; letter-spacing: -0.015em; line-height: 1.1; min-height: 2.25rem; } .kpi-sub { list-style: none; padding: 0; margin: 0.75rem 0 0; display: flex; flex-direction: column; gap: 0.25rem; font-size: 0.78125rem; color: var(--ink-soft); } .kpi-sub li { line-height: 1.35; } .kpi-cta { margin-top: 0.875rem; font-size: 0.75rem; font-weight: 700; color: var(--brand-700); letter-spacing: 0.02em; text-transform: uppercase; } .kpi-card:hover .kpi-cta { color: var(--brand-800); } /* Attention grid — auto-fill so the row of cards stays balanced */ .attention-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 0.875rem; } .attention-card { display: flex; flex-direction: column; gap: 0.375rem; padding: 1rem 1.125rem 1.125rem; text-decoration: none; color: inherit; border-left: 3px solid var(--line-strong); transition: transform 0.18s var(--ease-out-expo), box-shadow 0.18s; position: relative; } .attention-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); } .attention-card.tone-warn { border-left-color: var(--seguros); } .attention-card.tone-info { border-left-color: var(--brand-600); } .attention-card.tone-muted { border-left-color: var(--muted-2); } .attention-head { display: flex; align-items: center; justify-content: space-between; gap: 0.625rem; } .attention-title { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); font-weight: 700; } .attention-arrow { color: var(--muted-2); font-size: 0.875rem; transition: transform 0.18s var(--ease-out-expo), color 0.18s; } .attention-card:hover .attention-arrow { color: var(--brand-700); transform: translateX(3px); } .attention-primary { font-family: var(--font-display); font-size: 1.625rem; font-weight: 560; color: var(--ink); font-feature-settings: "tnum" 1; letter-spacing: -0.01em; line-height: 1.1; min-height: 1.875rem; margin-top: 0.125rem; } .attention-sub { font-size: 0.78125rem; color: var(--ink-soft); line-height: 1.4; } .attention-meta { font-size: 0.71875rem; color: var(--muted); margin-top: 0.25rem; } /* Currency totals inside an attention card */ .home-currency-totals { display: inline-flex; flex-wrap: wrap; gap: 0.5rem 0.875rem; align-items: baseline; } .home-currency-totals-row { display: inline-flex; align-items: baseline; gap: 0.375rem; } .home-currency-totals-num { font-family: var(--font-display); font-feature-settings: "tnum" 1; font-size: 1.25rem; font-weight: 560; } /* Quick links row */ .quick-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 0.75rem; } .quick-link { display: flex; flex-direction: column; padding: 0.875rem 1rem; text-decoration: none; color: inherit; position: relative; transition: transform 0.18s var(--ease-out-expo), box-shadow 0.18s; } .quick-link:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); } .quick-label { font-family: var(--font-display); font-size: 1.0625rem; font-weight: 560; color: var(--ink); } .quick-sub { font-size: 0.75rem; color: var(--muted); margin-top: 0.125rem; } .quick-arrow { position: absolute; top: 14px; right: 16px; color: var(--muted-2); font-size: 0.875rem; transition: transform 0.18s var(--ease-out-expo), color 0.18s; } .quick-link:hover .quick-arrow { color: var(--brand-700); transform: translateX(3px); } /* Money tone helpers (used in chequera card) */ .money-pos { color: var(--positive); } .money-neg { color: var(--negative); } /* ============================================================================ Reports module ========================================================================== */ .report-catalog { display: flex; flex-direction: column; gap: 1.75rem; margin-top: 1.25rem; } .report-catalog-group { display: flex; flex-direction: column; gap: 0.625rem; } .report-catalog-title { font-family: var(--font-display); font-weight: 500; font-size: 1.25rem; color: var(--brand-800); margin: 0; padding-bottom: 0.375rem; border-bottom: 1px solid var(--line); } .report-catalog-list { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 0.75rem; } .report-catalog-item { margin: 0; } .report-catalog-link { display: flex; flex-direction: column; gap: 0.375rem; padding: 0.875rem 1rem; background: var(--surface); border: 1px solid var(--line); border-radius: 8px; color: inherit; text-decoration: none; transition: border-color 0.18s, transform 0.18s var(--ease-out-expo); } .report-catalog-link:hover { border-color: var(--brand-500); transform: translateY(-1px); } .report-catalog-item-title { font-weight: 600; font-size: 0.9375rem; color: var(--ink); } .report-catalog-item-desc { font-size: 0.8125rem; color: var(--muted); line-height: 1.4; } .report-catalog-item-meta { display: flex; flex-wrap: wrap; gap: 0.375rem; margin-top: 0.25rem; } .report-catalog-tag { font-size: 0.6875rem; background: var(--brand-tint); color: var(--brand-800); padding: 0.125rem 0.5rem; border-radius: 999px; font-family: var(--font-mono); } .report-catalog-tag.muted { background: var(--paper-2); color: var(--muted); } /* Runner */ .report-runner { display: flex; flex-direction: column; gap: 1rem; margin-top: 1.25rem; } .report-filters { display: flex; flex-wrap: wrap; gap: 0.75rem; align-items: flex-end; background: var(--surface); border: 1px solid var(--line); border-radius: 8px; padding: 0.875rem 1rem; } .report-filters-actions { display: flex; align-items: center; gap: 0.5rem; margin-left: auto; } .report-error { background: #fbeae3; color: var(--negative); border: 1px solid #e6b6a4; border-radius: 6px; padding: 0.625rem 0.875rem; font-size: 0.8125rem; } .report-loading { font-size: 0.75rem; color: var(--muted); padding: 0.25rem 0; } .report-result { display: flex; flex-direction: column; gap: 0.75rem; } .report-result-head { display: flex; align-items: flex-end; gap: 1rem; flex-wrap: wrap; } .report-result-meta { flex: 1; min-width: 200px; } .report-output-buttons { display: flex; flex-wrap: wrap; gap: 0.375rem; } .btn-sm { padding: 0.25rem 0.625rem; font-size: 0.75rem; } .report-table-wrap { overflow-x: auto; background: var(--surface); border: 1px solid var(--line); border-radius: 8px; } .report-table { width: 100%; border-collapse: collapse; font-size: 0.8125rem; } .report-table th, .report-table td { padding: 0.5rem 0.75rem; border-bottom: 1px solid var(--line); } .report-table th { background: var(--paper-2); color: var(--ink-soft); font-weight: 600; text-align: left; position: sticky; top: 0; z-index: 1; } .report-table tbody tr:hover { background: var(--paper-2); } .report-totals { background: var(--accent); color: #f5f1e8; font-weight: 600; padding: 0.625rem 0.875rem; } .statement { display: flex; flex-direction: column; gap: 1.25rem; } .statement-head { background: var(--surface); border: 1px solid var(--line); border-radius: 8px; padding: 1rem 1.125rem; } .statement-name { font-family: var(--font-display); font-size: 1.375rem; font-weight: 600; color: var(--ink); margin: 0 0 0.25rem; } .statement-section-title { font-family: var(--font-display); font-size: 1rem; font-weight: 500; color: var(--brand-800); margin: 0 0 0.5rem; } /* Renewal notices (aviso-renovacion) — one card per policy due, see docs/RENEWAL_NOTICES.md for the legacy report this replaces. */ .renewal-letters { display: flex; flex-direction: column; gap: 1.25rem; } .renewal-letter { background: var(--surface); border: 1px solid var(--line); border-radius: 8px; padding: 1.125rem 1.25rem; break-inside: avoid; } .renewal-letter-head { display: flex; justify-content: space-between; align-items: flex-start; border-bottom: 1px solid var(--line); padding-bottom: 0.625rem; margin-bottom: 0.75rem; } .renewal-letter-title { font-family: var(--font-display); font-size: 1.125rem; font-weight: 600; color: var(--ink); margin: 0; } .renewal-letter-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0.75rem; margin-bottom: 0.75rem; } .renewal-letter-vehicle { background: var(--paper-2); border-radius: 6px; padding: 0.625rem 0.75rem; margin-bottom: 0.75rem; } .renewal-letter-coverage { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 0.75rem; margin-bottom: 0.75rem; } .renewal-letter-coverage-item { border-left: 2px solid var(--line-strong); padding-left: 0.625rem; } .renewal-letter-value { font-size: 0.875rem; font-weight: 600; color: var(--ink); margin: 0.125rem 0 0; } .renewal-letter-premium { display: flex; gap: 1.25rem; font-size: 0.875rem; border-top: 1px solid var(--line); padding-top: 0.625rem; } .renewal-letter-total { font-weight: 700; color: var(--brand-800); } @media print { .renewal-letter { page-break-inside: avoid; page-break-after: always; } .renewal-letter:last-child { page-break-after: auto; } } /* Context buttons (the inline shortcut on existing pages) */ .context-reports { display: flex; flex-wrap: wrap; gap: 0.375rem; align-items: center; margin-left: auto; } .context-reports-label { font-size: 0.6875rem; color: var(--muted-2); text-transform: uppercase; letter-spacing: 0.06em; margin-right: 0.25rem; font-weight: 500; } .context-report-link { font-size: 0.75rem; padding: 0.25rem 0.625rem; border: 1px solid var(--line); background: var(--surface); color: var(--ink); border-radius: 999px; text-decoration: none; transition: border-color 0.15s, color 0.15s; } .context-report-link:hover { border-color: var(--brand-500); color: var(--brand-700); }