25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1400 lines
30KB

  1. /* ── Design System Tokens ────────────────────────────────────────────── */
  2. :root {
  3. --primary: #1F4E79;
  4. --primary-dark: #163b5c;
  5. --primary-light: #dbeafe;
  6. --secondary: #0F766E;
  7. --accent: #2563EB;
  8. --success: #2E7D32;
  9. --success-bg: #F0FDF4;
  10. --success-border: #BBF7D0;
  11. --warning: #B45309;
  12. --warning-bg: #FFFBEB;
  13. --warning-border: #FDE68A;
  14. --error: #B91C1C;
  15. --error-bg: #FEF2F2;
  16. --error-border: #FECACA;
  17. --info: #2563EB;
  18. --info-bg: #EFF6FF;
  19. --info-border: #BFDBFE;
  20. --overdue: #7F1D1D;
  21. --bg: #F7F9FC;
  22. --surface: #FFFFFF;
  23. --surface-raised: #F8FAFC;
  24. --border: #D0D7E2;
  25. --border-strong: #9FB6D6;
  26. --text: #111827;
  27. --text-secondary: #4B5563;
  28. --text-muted: #6B7280;
  29. --radius-xs: 4px;
  30. --radius-sm: 6px;
  31. --radius: 8px;
  32. --radius-lg: 10px;
  33. --radius-xl: 12px;
  34. --shadow-xs: 0 1px 2px rgba(15, 23, 42, 0.06);
  35. --shadow-sm: 0 1px 4px rgba(15, 23, 42, 0.08);
  36. --shadow: 0 4px 12px rgba(15, 23, 42, 0.10);
  37. --shadow-md: 0 8px 24px rgba(15, 23, 42, 0.12);
  38. }
  39. /* ── Reset / Base ────────────────────────────────────────────────────── */
  40. *, *::before, *::after {
  41. box-sizing: border-box;
  42. }
  43. [x-cloak] {
  44. display: none !important;
  45. }
  46. html {
  47. scroll-behavior: smooth;
  48. }
  49. body {
  50. margin: 0;
  51. min-height: 100vh;
  52. font-family: "Public Sans", "Segoe UI", Arial, sans-serif;
  53. font-size: 14px;
  54. line-height: 22px;
  55. font-weight: 400;
  56. color: var(--text);
  57. background: var(--bg);
  58. overflow-x: hidden;
  59. }
  60. a {
  61. color: inherit;
  62. }
  63. code {
  64. font-family: "IBM Plex Mono", Consolas, "Courier New", monospace;
  65. font-size: 13px;
  66. }
  67. h1, h2, h3, h4, h5, h6 {
  68. margin: 0;
  69. font-weight: 600;
  70. color: var(--text);
  71. }
  72. h1 { font-size: 28px; line-height: 36px; }
  73. h2 { font-size: 22px; line-height: 30px; }
  74. h3 { font-size: 18px; line-height: 26px; }
  75. h4 { font-size: 16px; line-height: 24px; }
  76. /* ── Layout ──────────────────────────────────────────────────────────── */
  77. .page-shell {
  78. min-height: 100vh;
  79. display: flex;
  80. flex-direction: column;
  81. }
  82. .container {
  83. width: min(1200px, calc(100% - 2rem));
  84. margin: 0 auto;
  85. }
  86. /* ── Site Header ─────────────────────────────────────────────────────── */
  87. .site-header {
  88. position: sticky;
  89. top: 0;
  90. z-index: 20;
  91. background: var(--primary);
  92. border-bottom: 1px solid var(--primary-dark);
  93. box-shadow: var(--shadow-sm);
  94. }
  95. .header-inner {
  96. display: flex;
  97. align-items: center;
  98. justify-content: space-between;
  99. gap: 1rem;
  100. padding: 0;
  101. height: 52px;
  102. }
  103. .brand {
  104. display: inline-flex;
  105. align-items: center;
  106. gap: 10px;
  107. text-decoration: none;
  108. }
  109. .brand-mark {
  110. display: inline-flex;
  111. align-items: center;
  112. justify-content: center;
  113. width: 32px;
  114. height: 32px;
  115. border-radius: var(--radius-sm);
  116. background: rgba(255, 255, 255, 0.18);
  117. color: #fff;
  118. font-weight: 800;
  119. font-size: 12px;
  120. letter-spacing: 0.04em;
  121. flex-shrink: 0;
  122. }
  123. .brand-copy {
  124. display: flex;
  125. flex-direction: column;
  126. line-height: 1.2;
  127. }
  128. .brand-copy strong {
  129. font-size: 14px;
  130. font-weight: 700;
  131. color: #fff;
  132. letter-spacing: 0.01em;
  133. }
  134. .brand-copy small {
  135. color: rgba(255, 255, 255, 0.6);
  136. font-size: 11px;
  137. text-transform: uppercase;
  138. letter-spacing: 0.1em;
  139. }
  140. .site-nav {
  141. display: flex;
  142. align-items: center;
  143. gap: 2px;
  144. flex-wrap: wrap;
  145. }
  146. .nav-user {
  147. padding: 0 8px;
  148. color: rgba(255, 255, 255, 0.7);
  149. font-size: 13px;
  150. font-weight: 600;
  151. }
  152. .nav-logout-form {
  153. display: contents;
  154. }
  155. .nav-link {
  156. display: inline-flex;
  157. align-items: center;
  158. gap: 6px;
  159. text-decoration: none;
  160. color: rgba(255, 255, 255, 0.88);
  161. font-size: 13px;
  162. font-weight: 600;
  163. padding: 6px 12px;
  164. border-radius: var(--radius-sm);
  165. transition: background-color 120ms ease, color 120ms ease;
  166. }
  167. .nav-link:hover {
  168. color: #fff;
  169. background: rgba(255, 255, 255, 0.12);
  170. }
  171. .nav-link:focus-visible {
  172. color: #fff;
  173. background: rgba(255, 255, 255, 0.12);
  174. outline: 2px solid rgba(255, 255, 255, 0.6);
  175. outline-offset: 2px;
  176. }
  177. .nav-link.is-active {
  178. color: #fff;
  179. background: rgba(255, 255, 255, 0.18);
  180. }
  181. .nav-sep {
  182. width: 1px;
  183. height: 18px;
  184. background: rgba(255, 255, 255, 0.2);
  185. margin: 0 4px;
  186. flex-shrink: 0;
  187. }
  188. .nav-logout-btn {
  189. display: inline-flex;
  190. align-items: center;
  191. padding: 4px 10px;
  192. border-radius: var(--radius-xs);
  193. font-family: inherit;
  194. font-size: 12px;
  195. font-weight: 600;
  196. line-height: 20px;
  197. cursor: pointer;
  198. background: transparent;
  199. color: rgba(255, 255, 255, 0.75);
  200. border: 1px solid rgba(255, 255, 255, 0.22);
  201. transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease;
  202. }
  203. .nav-logout-btn:hover {
  204. background: rgba(255, 255, 255, 0.1);
  205. border-color: rgba(255, 255, 255, 0.4);
  206. color: #fff;
  207. }
  208. .nav-logout-btn:focus-visible {
  209. outline: 2px solid rgba(255, 255, 255, 0.6);
  210. outline-offset: 2px;
  211. }
  212. /* ── Page Content ────────────────────────────────────────────────────── */
  213. .page-content {
  214. flex: 1;
  215. padding: 32px 0 40px;
  216. }
  217. .content-stack {
  218. display: grid;
  219. gap: 24px;
  220. }
  221. /* ── Section Heading ─────────────────────────────────────────────────── */
  222. .section-heading {
  223. max-width: 720px;
  224. }
  225. .section-heading h1 {
  226. margin: 4px 0 8px;
  227. font-size: 32px;
  228. line-height: 40px;
  229. }
  230. .section-heading p {
  231. margin: 0;
  232. color: var(--text-secondary);
  233. line-height: 22px;
  234. font-size: 14px;
  235. }
  236. /* ── Hero (home page) ────────────────────────────────────────────────── */
  237. .hero {
  238. display: grid;
  239. grid-template-columns: minmax(0, 1.5fr) minmax(280px, 0.9fr);
  240. gap: 16px;
  241. align-items: stretch;
  242. }
  243. .hero-copy,
  244. .hero-panel,
  245. .feature-card,
  246. .section-panel,
  247. .alert,
  248. .empty-state {
  249. background: var(--surface);
  250. border: 1px solid var(--border);
  251. box-shadow: var(--shadow-sm);
  252. }
  253. .hero-copy {
  254. padding: 32px;
  255. border-radius: var(--radius-lg);
  256. }
  257. .eyebrow {
  258. display: inline-block;
  259. margin-bottom: 16px;
  260. padding: 3px 10px;
  261. border-radius: 999px;
  262. background: var(--info-bg);
  263. border: 1px solid var(--info-border);
  264. color: var(--accent);
  265. font-size: 11px;
  266. font-weight: 700;
  267. text-transform: uppercase;
  268. letter-spacing: 0.1em;
  269. }
  270. .hero h1 {
  271. font-size: clamp(24px, 4vw, 36px);
  272. line-height: 1.15;
  273. letter-spacing: -0.02em;
  274. color: var(--primary);
  275. }
  276. .hero-text {
  277. max-width: 560px;
  278. margin: 16px 0 0;
  279. font-size: 14px;
  280. line-height: 22px;
  281. color: var(--text-secondary);
  282. }
  283. .hero-actions {
  284. display: flex;
  285. flex-wrap: wrap;
  286. gap: 8px;
  287. margin-top: 24px;
  288. }
  289. .hero-panel {
  290. display: flex;
  291. flex-direction: column;
  292. justify-content: space-between;
  293. padding: 24px;
  294. border-radius: var(--radius-lg);
  295. }
  296. .panel-label {
  297. margin: 0 0 12px;
  298. font-size: 11px;
  299. font-weight: 700;
  300. letter-spacing: 0.1em;
  301. text-transform: uppercase;
  302. color: var(--text-secondary);
  303. }
  304. .hero-panel code {
  305. display: block;
  306. padding: 12px 14px;
  307. border-radius: var(--radius);
  308. background: #0f172a;
  309. color: #e2e8f0;
  310. font-family: "IBM Plex Mono", Consolas, monospace;
  311. font-size: 12px;
  312. line-height: 20px;
  313. white-space: normal;
  314. }
  315. .route-callout {
  316. margin-top: 16px;
  317. padding: 12px 14px;
  318. border-radius: var(--radius);
  319. background: var(--surface-raised);
  320. border: 1px solid var(--border);
  321. }
  322. .route-callout span {
  323. display: block;
  324. margin-bottom: 6px;
  325. color: var(--text-secondary);
  326. font-size: 13px;
  327. }
  328. .route-callout a {
  329. color: var(--accent);
  330. font-weight: 700;
  331. text-decoration: none;
  332. }
  333. /* ── Feature Grid ────────────────────────────────────────────────────── */
  334. .feature-grid {
  335. display: grid;
  336. grid-template-columns: repeat(3, minmax(0, 1fr));
  337. gap: 16px;
  338. margin-top: 16px;
  339. }
  340. .feature-card {
  341. padding: 20px;
  342. border-radius: var(--radius-lg);
  343. }
  344. .feature-card h2 {
  345. margin-top: 0;
  346. margin-bottom: 8px;
  347. font-size: 16px;
  348. line-height: 24px;
  349. }
  350. .feature-card p {
  351. margin: 0;
  352. color: var(--text-secondary);
  353. line-height: 22px;
  354. font-size: 13px;
  355. }
  356. /* ── Panels & Controls ───────────────────────────────────────────────── */
  357. .controls-panel,
  358. .table-shell {
  359. overflow: hidden;
  360. background: var(--surface);
  361. border: 1px solid var(--border);
  362. }
  363. .controls-header {
  364. display: flex;
  365. align-items: flex-start;
  366. justify-content: space-between;
  367. gap: 16px;
  368. }
  369. .search-row {
  370. display: grid;
  371. grid-template-columns: minmax(0, 1fr);
  372. }
  373. .field-full {
  374. width: 100%;
  375. }
  376. .section-panel {
  377. padding: 24px;
  378. border-radius: var(--radius-lg);
  379. min-width: 0;
  380. border-left: 3px solid var(--primary);
  381. }
  382. .panel-header {
  383. display: flex;
  384. align-items: flex-start;
  385. justify-content: space-between;
  386. gap: 16px;
  387. flex-wrap: wrap;
  388. margin-bottom: 20px;
  389. padding-bottom: 16px;
  390. border-bottom: 1px solid var(--border);
  391. }
  392. .panel-actions {
  393. display: flex;
  394. align-items: center;
  395. gap: 8px;
  396. flex-wrap: wrap;
  397. }
  398. .panel-header h2 {
  399. margin: 0 0 4px;
  400. font-size: 18px;
  401. line-height: 26px;
  402. }
  403. .panel-header p {
  404. margin: 0;
  405. color: var(--text-secondary);
  406. line-height: 22px;
  407. font-size: 13px;
  408. }
  409. .job-type-table-stack {
  410. display: grid;
  411. gap: 16px;
  412. }
  413. .job-type-table-group {
  414. display: grid;
  415. gap: 8px;
  416. padding-top: 16px;
  417. border-top: 1px solid var(--border);
  418. }
  419. .job-type-table-group:first-child {
  420. padding-top: 0;
  421. border-top: 0;
  422. }
  423. .job-type-table-heading {
  424. display: flex;
  425. align-items: center;
  426. justify-content: space-between;
  427. gap: 16px;
  428. flex-wrap: wrap;
  429. }
  430. .job-type-table-heading h3 {
  431. margin: 0;
  432. font-size: 15px;
  433. line-height: 22px;
  434. }
  435. .job-type-table-heading span {
  436. color: var(--text-secondary);
  437. font-size: 12px;
  438. font-weight: 700;
  439. }
  440. /* ── Forms ───────────────────────────────────────────────────────────── */
  441. .form-grid {
  442. display: grid;
  443. grid-template-columns: repeat(2, minmax(0, 1fr));
  444. gap: 16px;
  445. }
  446. .field {
  447. display: grid;
  448. gap: 6px;
  449. font-weight: 600;
  450. font-size: 13px;
  451. }
  452. .field span {
  453. font-size: 13px;
  454. color: var(--text);
  455. }
  456. .input {
  457. width: 100%;
  458. padding: 7px 10px;
  459. border: 1px solid var(--border);
  460. border-radius: var(--radius-sm);
  461. background: var(--surface);
  462. color: var(--text);
  463. font: inherit;
  464. font-size: 14px;
  465. line-height: 20px;
  466. transition: border-color 120ms ease, box-shadow 120ms ease;
  467. }
  468. .input:focus {
  469. outline: none;
  470. border-color: var(--accent);
  471. box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.12);
  472. }
  473. .input:invalid:not(:placeholder-shown) {
  474. border-color: var(--error);
  475. box-shadow: 0 0 0 3px rgba(185, 28, 28, 0.08);
  476. }
  477. .field-error {
  478. color: var(--error);
  479. font-size: 12px;
  480. font-weight: 600;
  481. }
  482. .form-actions {
  483. display: flex;
  484. justify-content: flex-start;
  485. align-items: center;
  486. gap: 8px;
  487. }
  488. .ct-form .form-actions {
  489. position: sticky;
  490. bottom: 0;
  491. z-index: 2;
  492. background: var(--surface);
  493. margin: 8px -24px -24px;
  494. padding: 12px 24px;
  495. border-top: 1px solid var(--border);
  496. border-radius: 0 0 var(--radius-lg) var(--radius-lg);
  497. }
  498. /* ── Buttons ─────────────────────────────────────────────────────────── */
  499. .button {
  500. display: inline-flex;
  501. align-items: center;
  502. justify-content: center;
  503. padding: 7px 16px;
  504. border-radius: var(--radius-sm);
  505. text-decoration: none;
  506. font-family: inherit;
  507. font-size: 13px;
  508. font-weight: 600;
  509. line-height: 20px;
  510. border: 1px solid transparent;
  511. cursor: pointer;
  512. transition: background-color 120ms ease, border-color 120ms ease, box-shadow 120ms ease;
  513. }
  514. .button:focus-visible {
  515. outline: 2px solid var(--accent);
  516. outline-offset: 2px;
  517. }
  518. .button-primary {
  519. background: var(--primary);
  520. color: #fff;
  521. border-color: var(--primary-dark);
  522. }
  523. .button-primary:hover {
  524. background: var(--primary-dark);
  525. }
  526. .button-secondary {
  527. background: var(--surface);
  528. color: var(--text);
  529. border-color: var(--border);
  530. }
  531. .button-secondary:hover {
  532. background: var(--surface-raised);
  533. border-color: var(--border-strong);
  534. }
  535. .button-danger {
  536. background: var(--error);
  537. color: #fff;
  538. border-color: #991B1B;
  539. }
  540. .button-danger:hover,
  541. .button-danger:focus-visible {
  542. background: #991B1B;
  543. }
  544. .button-sm {
  545. padding: 4px 10px;
  546. font-size: 12px;
  547. border-radius: var(--radius-xs);
  548. border: 1px solid transparent;
  549. cursor: pointer;
  550. }
  551. /* ── Alerts & Empty States ───────────────────────────────────────────── */
  552. .alert,
  553. .empty-state {
  554. padding: 12px 16px;
  555. border-radius: var(--radius);
  556. font-size: 14px;
  557. }
  558. .alert-success {
  559. background: var(--success-bg);
  560. border-color: var(--success-border);
  561. color: var(--success);
  562. }
  563. .alert-error {
  564. background: var(--error-bg);
  565. border-color: var(--error-border);
  566. color: var(--error);
  567. }
  568. .empty-state p {
  569. margin: 0;
  570. color: var(--text-secondary);
  571. line-height: 22px;
  572. }
  573. .empty-state p + p {
  574. margin-top: 6px;
  575. }
  576. /* ── Stats Grid ──────────────────────────────────────────────────────── */
  577. .stats-grid {
  578. display: grid;
  579. grid-template-columns: repeat(3, minmax(0, 1fr));
  580. gap: 12px;
  581. }
  582. .stat-card {
  583. padding: 16px;
  584. border-radius: var(--radius);
  585. background: var(--surface);
  586. border: 1px solid var(--border);
  587. box-shadow: var(--shadow-xs);
  588. }
  589. .stat-card span {
  590. display: block;
  591. color: var(--text-secondary);
  592. font-size: 11px;
  593. text-transform: uppercase;
  594. letter-spacing: 0.08em;
  595. font-weight: 600;
  596. }
  597. .stat-card strong {
  598. display: block;
  599. margin-top: 8px;
  600. font-size: 38px;
  601. line-height: 1;
  602. font-weight: 700;
  603. color: var(--primary);
  604. }
  605. a.stat-card {
  606. text-decoration: none;
  607. cursor: pointer;
  608. transition: transform 100ms ease, box-shadow 100ms ease, border-color 100ms ease;
  609. }
  610. a.stat-card:hover {
  611. transform: translateY(-2px);
  612. box-shadow: var(--shadow);
  613. border-color: var(--border-strong);
  614. }
  615. a.stat-card:focus-visible {
  616. outline: 2px solid var(--accent);
  617. outline-offset: 2px;
  618. }
  619. a.stat-card::after {
  620. content: 'View all →';
  621. display: block;
  622. margin-top: 10px;
  623. font-size: 11px;
  624. font-weight: 600;
  625. letter-spacing: 0.04em;
  626. color: var(--text-muted);
  627. opacity: 0;
  628. transform: translateX(-4px);
  629. transition: opacity 150ms ease, transform 150ms ease;
  630. }
  631. a.stat-card:hover::after {
  632. opacity: 1;
  633. transform: translateX(0);
  634. }
  635. .summary-feature {
  636. margin-top: 16px;
  637. padding: 14px 16px;
  638. border-radius: var(--radius);
  639. background: var(--info-bg);
  640. border: 1px solid var(--info-border);
  641. }
  642. .summary-label {
  643. display: block;
  644. color: var(--text-secondary);
  645. font-size: 11px;
  646. text-transform: uppercase;
  647. letter-spacing: 0.08em;
  648. font-weight: 600;
  649. }
  650. .summary-feature h3 {
  651. margin: 6px 0 4px;
  652. font-size: 16px;
  653. line-height: 24px;
  654. color: var(--primary);
  655. }
  656. .summary-feature p {
  657. margin: 0;
  658. color: var(--text-secondary);
  659. font-size: 13px;
  660. }
  661. /* ── Dashboard ───────────────────────────────────────────────────────── */
  662. .stats-grid-4 {
  663. grid-template-columns: repeat(4, minmax(0, 1fr));
  664. }
  665. .dashboard-panels {
  666. display: grid;
  667. grid-template-columns: 1fr 1fr;
  668. gap: 16px;
  669. align-items: start;
  670. }
  671. .dashboard-table {
  672. width: 100%;
  673. border-collapse: collapse;
  674. font-size: 13px;
  675. }
  676. .dashboard-table th {
  677. text-align: left;
  678. padding: 6px 10px;
  679. font-size: 11px;
  680. text-transform: uppercase;
  681. letter-spacing: 0.06em;
  682. color: var(--text-secondary);
  683. border-bottom: 1px solid var(--border);
  684. }
  685. .dashboard-table td {
  686. padding: 8px 10px;
  687. border-bottom: 1px solid var(--border);
  688. color: var(--text-primary);
  689. }
  690. .dashboard-table tr:last-child td {
  691. border-bottom: none;
  692. }
  693. .dashboard-table-id {
  694. color: var(--text-secondary);
  695. font-variant-numeric: tabular-nums;
  696. width: 48px;
  697. }
  698. .dashboard-table-date {
  699. color: var(--text-secondary);
  700. white-space: nowrap;
  701. }
  702. .dashboard-table-action {
  703. text-align: right;
  704. width: 40px;
  705. }
  706. .dashboard-table-action a {
  707. color: var(--primary);
  708. font-size: 12px;
  709. }
  710. .type-breakdown {
  711. display: flex;
  712. flex-direction: column;
  713. gap: 10px;
  714. padding: 4px 0;
  715. }
  716. .type-breakdown-row {
  717. display: grid;
  718. grid-template-columns: 140px 1fr 36px;
  719. align-items: center;
  720. gap: 10px;
  721. font-size: 13px;
  722. }
  723. .type-name {
  724. color: var(--text-primary);
  725. white-space: nowrap;
  726. overflow: hidden;
  727. text-overflow: ellipsis;
  728. }
  729. .type-bar-wrap {
  730. height: 8px;
  731. background: var(--border);
  732. border-radius: 4px;
  733. overflow: hidden;
  734. }
  735. .type-bar {
  736. display: block;
  737. height: 100%;
  738. background: var(--primary);
  739. border-radius: 4px;
  740. min-width: 4px;
  741. transition: width 0.3s ease;
  742. }
  743. .type-count {
  744. text-align: right;
  745. font-variant-numeric: tabular-nums;
  746. color: var(--text-secondary);
  747. font-size: 12px;
  748. }
  749. @media (max-width: 860px) {
  750. .stats-grid-4 {
  751. grid-template-columns: repeat(2, minmax(0, 1fr));
  752. }
  753. .dashboard-panels {
  754. grid-template-columns: 1fr;
  755. }
  756. }
  757. /* ── Table Toolbar ───────────────────────────────────────────────────── */
  758. .table-toolbar {
  759. display: flex;
  760. align-items: center;
  761. justify-content: space-between;
  762. gap: 16px;
  763. margin-bottom: 12px;
  764. flex-wrap: wrap;
  765. padding: 8px 12px;
  766. border: 1px solid var(--border);
  767. border-radius: var(--radius);
  768. background: var(--surface);
  769. }
  770. .table-pill {
  771. display: inline-flex;
  772. align-items: center;
  773. padding: 3px 10px;
  774. border-radius: 999px;
  775. background: var(--info-bg);
  776. border: 1px solid var(--info-border);
  777. color: var(--accent);
  778. font-size: 12px;
  779. font-weight: 700;
  780. letter-spacing: 0.04em;
  781. }
  782. .table-caption {
  783. color: var(--text-secondary);
  784. font-size: 12px;
  785. }
  786. /* ── Tabulator ───────────────────────────────────────────────────────── */
  787. .tabulator-host {
  788. overflow-x: auto;
  789. width: 100%;
  790. }
  791. .directory-panel .tabulator-host {
  792. min-height: 38rem;
  793. }
  794. .tabulator-host .tabulator {
  795. border: 1px solid var(--border);
  796. border-radius: var(--radius-lg);
  797. overflow: hidden;
  798. background: var(--surface);
  799. box-shadow: var(--shadow-sm);
  800. }
  801. .tabulator-host .tabulator-header {
  802. border-bottom: 1px solid var(--border);
  803. background: var(--surface-raised);
  804. }
  805. .tabulator-host .tabulator-header .tabulator-col {
  806. min-height: 36px;
  807. background: transparent;
  808. border-right: 1px solid var(--border);
  809. }
  810. .tabulator-host .tabulator-header .tabulator-col:last-child {
  811. border-right: 0;
  812. }
  813. .tabulator-host .tabulator-header .tabulator-col .tabulator-col-content {
  814. padding: 8px 10px;
  815. }
  816. .tabulator-host .tabulator-header .tabulator-col .tabulator-col-title {
  817. font-size: 11px;
  818. font-weight: 700;
  819. letter-spacing: 0.06em;
  820. text-transform: uppercase;
  821. color: var(--text-secondary);
  822. }
  823. .tabulator-host .tabulator-col,
  824. .tabulator-host .tabulator-cell {
  825. border-right: 1px solid var(--border);
  826. }
  827. .tabulator-host .tabulator-row .tabulator-cell:last-child {
  828. border-right: 0;
  829. }
  830. .tabulator-host .tabulator-row {
  831. background: var(--surface);
  832. border-bottom: 1px solid var(--border);
  833. transition: background-color 100ms ease;
  834. }
  835. .tabulator-host .tabulator-row:nth-child(even) {
  836. background: var(--surface-raised);
  837. }
  838. .tabulator-host .tabulator-row:hover {
  839. background: var(--info-bg);
  840. }
  841. .tabulator-host .tabulator-row.tabulator-selected {
  842. background: var(--primary-light);
  843. }
  844. .tabulator-host .tabulator-cell {
  845. padding: 8px 10px;
  846. font-size: 13px;
  847. line-height: 20px;
  848. }
  849. .tabulator-host .tabulator-row .tabulator-cell:first-child {
  850. font-weight: 600;
  851. color: var(--text);
  852. }
  853. .tabulator-host .tabulator-footer {
  854. padding: 6px 8px;
  855. background: var(--surface-raised);
  856. border-top: 1px solid var(--border);
  857. }
  858. .tabulator-host .tabulator-footer .tabulator-paginator {
  859. font-family: inherit;
  860. font-size: 13px;
  861. }
  862. .tabulator-host .tabulator-footer .tabulator-page {
  863. margin: 0 2px;
  864. padding: 4px 8px;
  865. border: 1px solid var(--border);
  866. border-radius: var(--radius-xs);
  867. background: var(--surface);
  868. color: var(--text-secondary);
  869. font-weight: 600;
  870. font-size: 12px;
  871. }
  872. .tabulator-host .tabulator-footer .tabulator-page.active,
  873. .tabulator-host .tabulator-footer .tabulator-page:hover {
  874. background: var(--primary);
  875. border-color: var(--primary-dark);
  876. color: #fff;
  877. }
  878. .tabulator-host .tabulator-footer .tabulator-page:disabled {
  879. opacity: 0.4;
  880. }
  881. .tabulator-host .tabulator-placeholder {
  882. padding: 32px 16px;
  883. color: var(--text-secondary);
  884. font-size: 13px;
  885. font-weight: 600;
  886. }
  887. /* ── HTMX Indicators ─────────────────────────────────────────────────── */
  888. .htmx-indicator {
  889. display: none;
  890. }
  891. .htmx-request .htmx-indicator,
  892. .htmx-request.htmx-indicator {
  893. display: inline-flex;
  894. }
  895. .inline-indicator {
  896. color: var(--text-secondary);
  897. font-size: 13px;
  898. font-weight: 600;
  899. }
  900. /* ── Site Footer ─────────────────────────────────────────────────────── */
  901. .site-footer {
  902. margin-top: auto;
  903. border-top: 1px solid var(--border);
  904. background: var(--surface);
  905. }
  906. .footer-inner {
  907. display: flex;
  908. justify-content: space-between;
  909. gap: 16px;
  910. padding: 16px 0 24px;
  911. color: var(--text-muted);
  912. font-size: 12px;
  913. line-height: 18px;
  914. }
  915. .footer-inner p {
  916. margin: 0;
  917. }
  918. /* ── Page Toolbar ────────────────────────────────────────────────────── */
  919. .page-toolbar {
  920. display: flex;
  921. align-items: flex-start;
  922. justify-content: space-between;
  923. gap: 16px;
  924. flex-wrap: wrap;
  925. }
  926. .page-toolbar .section-heading {
  927. margin: 0;
  928. }
  929. .page-toolbar .section-heading h1 {
  930. margin: 0 0 4px;
  931. }
  932. /* ── Campaign Types / Import Forms ───────────────────────────────────── */
  933. .ct-form {
  934. display: grid;
  935. gap: 24px;
  936. }
  937. .form-section {
  938. display: grid;
  939. gap: 12px;
  940. }
  941. .form-section h3 {
  942. margin: 0;
  943. font-size: 15px;
  944. line-height: 22px;
  945. }
  946. .attributes-header {
  947. display: flex;
  948. flex-direction: column;
  949. gap: 4px;
  950. }
  951. .attributes-hint {
  952. margin: 0;
  953. color: var(--text-secondary);
  954. font-size: 13px;
  955. }
  956. .attribute-list {
  957. display: grid;
  958. gap: 6px;
  959. }
  960. .attribute-row {
  961. display: flex;
  962. align-items: flex-end;
  963. gap: 8px;
  964. flex-wrap: wrap;
  965. }
  966. .attr-drag-handle {
  967. cursor: grab;
  968. user-select: none;
  969. align-self: flex-end;
  970. padding-bottom: 8px;
  971. font-size: 0;
  972. display: inline-flex;
  973. align-items: center;
  974. justify-content: center;
  975. width: 18px;
  976. height: 34px;
  977. flex-shrink: 0;
  978. opacity: 0.5;
  979. transition: opacity 100ms ease;
  980. }
  981. .attr-drag-handle::before {
  982. content: '';
  983. display: block;
  984. width: 6px;
  985. height: 16px;
  986. background-image: radial-gradient(circle, var(--text-muted) 1.5px, transparent 1.5px);
  987. background-size: 3px 4px;
  988. background-repeat: repeat;
  989. }
  990. .attr-drag-handle:hover {
  991. opacity: 1;
  992. }
  993. .attr-drag-handle:active {
  994. cursor: grabbing;
  995. opacity: 1;
  996. }
  997. .attribute-row.is-dragging {
  998. opacity: 0.35;
  999. }
  1000. .attribute-row.is-drag-over {
  1001. outline: 2px dashed var(--accent);
  1002. border-radius: var(--radius-sm);
  1003. background: var(--info-bg);
  1004. }
  1005. .attribute-order-field {
  1006. flex: 0 0 5rem;
  1007. min-width: 5rem;
  1008. }
  1009. .attribute-order-field .input {
  1010. text-align: center;
  1011. }
  1012. .attribute-name-field {
  1013. flex: 2;
  1014. min-width: 160px;
  1015. }
  1016. .attribute-type-field {
  1017. flex: 1;
  1018. min-width: 110px;
  1019. }
  1020. .attribute-remove {
  1021. padding-bottom: 0.1rem;
  1022. }
  1023. .input-error {
  1024. border-color: var(--error) !important;
  1025. }
  1026. .required-mark {
  1027. color: var(--error);
  1028. }
  1029. .delete-zone {
  1030. margin-top: 32px;
  1031. padding-top: 16px;
  1032. border-top: 1px solid var(--error-border);
  1033. }
  1034. .delete-zone h4 {
  1035. margin: 0 0 4px;
  1036. color: var(--error);
  1037. font-size: 14px;
  1038. }
  1039. .delete-zone p {
  1040. margin: 0 0 12px;
  1041. color: var(--text-secondary);
  1042. font-size: 13px;
  1043. }
  1044. .attr-summary {
  1045. color: var(--text-secondary);
  1046. font-size: 13px;
  1047. }
  1048. .attr-empty {
  1049. color: var(--text-muted);
  1050. opacity: 0.6;
  1051. }
  1052. /* ── Import Tabs ─────────────────────────────────────────────────────── */
  1053. .import-tabs {
  1054. display: flex;
  1055. gap: 2px;
  1056. margin-bottom: 16px;
  1057. border-bottom: 1px solid var(--border);
  1058. padding-bottom: 0;
  1059. }
  1060. .import-tab {
  1061. padding: 6px 14px;
  1062. border: none;
  1063. background: none;
  1064. cursor: pointer;
  1065. font: inherit;
  1066. font-size: 13px;
  1067. font-weight: 600;
  1068. color: var(--text-secondary);
  1069. border-bottom: 2px solid transparent;
  1070. margin-bottom: -1px;
  1071. border-radius: 0;
  1072. transition: color 120ms, border-color 120ms;
  1073. }
  1074. .import-tab:hover { color: var(--accent); }
  1075. .import-tab.is-active { color: var(--primary); border-bottom-color: var(--primary); }
  1076. .import-grid {
  1077. display: grid;
  1078. grid-template-columns: minmax(260px, 1.4fr) minmax(180px, 0.8fr) minmax(180px, 0.8fr);
  1079. gap: 16px;
  1080. }
  1081. .import-actions {
  1082. margin-top: 16px;
  1083. flex-wrap: wrap;
  1084. }
  1085. /* Campaign jobs table — horizontal scroll inside the panel */
  1086. #campaign-jobs-page-table {
  1087. overflow-x: auto;
  1088. width: 100%;
  1089. }
  1090. /* ── Global Focus Visible ────────────────────────────────────────────── */
  1091. .page-content a:focus-visible {
  1092. outline: 2px solid var(--accent);
  1093. outline-offset: 2px;
  1094. border-radius: 2px;
  1095. }
  1096. /* ── Skeleton Loading ────────────────────────────────────────────────── */
  1097. @keyframes skeleton-shimmer {
  1098. 0% { background-position: 200% 0; }
  1099. 100% { background-position: -200% 0; }
  1100. }
  1101. .skeleton-rows {
  1102. display: flex;
  1103. flex-direction: column;
  1104. gap: 8px;
  1105. padding: 4px 0;
  1106. }
  1107. .skeleton-row {
  1108. height: 38px;
  1109. border-radius: var(--radius-sm);
  1110. background: linear-gradient(90deg, var(--surface-raised) 25%, var(--border) 50%, var(--surface-raised) 75%);
  1111. background-size: 400% 100%;
  1112. animation: skeleton-shimmer 1.5s ease-in-out infinite;
  1113. }
  1114. .skeleton-row:nth-child(2) { animation-delay: 0.1s; opacity: 0.85; }
  1115. .skeleton-row:nth-child(3) { animation-delay: 0.2s; opacity: 0.7; }
  1116. .skeleton-row:nth-child(4) { animation-delay: 0.3s; opacity: 0.55; }
  1117. .skeleton-row:nth-child(5) { animation-delay: 0.4s; opacity: 0.4; }
  1118. /* ── Type Breakdown Links ────────────────────────────────────────────── */
  1119. a.type-breakdown-row {
  1120. text-decoration: none;
  1121. color: inherit;
  1122. padding: 4px 6px;
  1123. margin: 0 -6px;
  1124. border-radius: var(--radius-sm);
  1125. transition: background-color 100ms ease;
  1126. }
  1127. a.type-breakdown-row:hover {
  1128. background: var(--surface-raised);
  1129. }
  1130. a.type-breakdown-row:focus-visible {
  1131. outline: 2px solid var(--accent);
  1132. outline-offset: 2px;
  1133. }
  1134. /* ── Responsive ──────────────────────────────────────────────────────── */
  1135. @media (max-width: 860px) {
  1136. .header-inner,
  1137. .footer-inner {
  1138. flex-direction: column;
  1139. align-items: flex-start;
  1140. }
  1141. .header-inner {
  1142. height: auto;
  1143. padding: 12px 0;
  1144. }
  1145. .hero,
  1146. .feature-grid {
  1147. grid-template-columns: 1fr;
  1148. }
  1149. .controls-header,
  1150. .table-toolbar {
  1151. flex-direction: column;
  1152. align-items: flex-start;
  1153. }
  1154. .hero-copy,
  1155. .hero-panel {
  1156. padding: 24px;
  1157. }
  1158. .form-grid {
  1159. grid-template-columns: 1fr;
  1160. }
  1161. .import-grid {
  1162. grid-template-columns: 1fr;
  1163. }
  1164. .stats-grid {
  1165. grid-template-columns: 1fr;
  1166. }
  1167. .page-content {
  1168. padding-top: 24px;
  1169. }
  1170. }
  1171. @media (max-width: 560px) {
  1172. .container {
  1173. width: min(100% - 1rem, 1200px);
  1174. }
  1175. .site-nav {
  1176. width: 100%;
  1177. }
  1178. .nav-link {
  1179. width: 100%;
  1180. text-align: center;
  1181. }
  1182. .nav-sep {
  1183. display: none;
  1184. }
  1185. .hero h1 {
  1186. font-size: 22px;
  1187. }
  1188. }

Powered by TurnKey Linux.