:root{ --paper:#F7F5F0; --card:#FFFFFF; --ink:#12233A; --ink-soft:#2A3B50; --muted:#6B7480; --hair:#E1DDD3; --hair-2:#EDEAE2; --aqua:#17B0A6; --aqua-deep:#0E6E68; --signal:#E8963A; --danger:#C24A3A; --radius:12px; } *{box-sizing:border-box} body{ margin:0;background:var(--paper);color:var(--ink); font-family:"IBM Plex Sans",system-ui,sans-serif;font-size:15px;line-height:1.55; -webkit-font-smoothing:antialiased; } a{color:var(--aqua-deep)} .muted{color:var(--muted)} code{font-family:"IBM Plex Mono",monospace;font-size:.85em;background:var(--hair-2);padding:1px 5px;border-radius:5px} /* nav */ .anav{ display:flex;align-items:center;justify-content:space-between; padding:14px 26px;background:var(--ink);color:var(--paper); position:sticky;top:0;z-index:10; } .anav__brand{ font-family:"Bricolage Grotesque",sans-serif;font-weight:700;font-size:1.2rem; color:var(--paper);text-decoration:none;letter-spacing:-.01em; } .anav__brand span{ font-family:"IBM Plex Mono",monospace;font-weight:500;font-size:.7rem; letter-spacing:.18em;text-transform:uppercase;color:var(--aqua);margin-left:8px; } .anav__right{display:flex;align-items:center;gap:16px} .anav__link{color:rgba(247,245,240,.8);text-decoration:none;font-size:.86rem} .anav__link:hover{color:var(--aqua)} .anav__user{ font-family:"IBM Plex Mono",monospace;font-size:.78rem;color:rgba(247,245,240,.55); } .anav form{margin:0} /* layout */ .awrap{max-width:900px;margin:0 auto;padding:32px 26px 80px} .page-head{ display:flex;align-items:flex-start;justify-content:space-between;gap:20px; margin-bottom:26px;flex-wrap:wrap; } .page-head h1{ font-family:"Bricolage Grotesque",sans-serif;font-weight:700; font-size:1.9rem;letter-spacing:-.02em;margin:0 0 4px; } .page-head__actions{display:flex;gap:10px} /* flashes */ .flashes{margin-bottom:20px;display:flex;flex-direction:column;gap:8px} .flash{padding:11px 15px;border-radius:10px;font-size:.9rem;border:1px solid transparent} .flash--ok{background:#E7F6F4;border-color:#B9E6E0;color:#0A5A54} .flash--error{background:#FBEAE6;border-color:#F0C7BE;color:#9C3325} /* buttons */ .btn{ display:inline-flex;align-items:center;gap:6px;cursor:pointer;text-decoration:none; font-family:"IBM Plex Sans",sans-serif;font-weight:600;font-size:.88rem; padding:9px 16px;border-radius:100px;border:1px solid transparent;line-height:1; transition:background .18s,border-color .18s,color .18s,transform .18s; } .btn--sm{padding:6px 12px;font-size:.8rem} .btn--primary{background:var(--aqua);color:#04201E} .btn--primary:hover{background:var(--aqua-deep);color:#fff} .btn--ghost{background:var(--card);border-color:var(--hair);color:var(--ink-soft)} .btn--ghost:hover{border-color:var(--aqua);color:var(--aqua-deep)} .btn--danger{background:transparent;border-color:var(--hair);color:var(--danger)} .btn--danger:hover{background:var(--danger);border-color:var(--danger);color:#fff} form{display:inline} /* section cards */ .sec-card{ background:var(--card);border:1px solid var(--hair);border-radius:var(--radius); margin-bottom:18px;overflow:hidden; } .sec-card__head{ display:flex;align-items:center;justify-content:space-between;gap:14px; padding:16px 18px;border-bottom:1px solid var(--hair-2);flex-wrap:wrap; } .sec-card__meta{display:flex;align-items:center;gap:12px;flex-wrap:wrap} .sec-card__meta h2{ font-family:"Bricolage Grotesque",sans-serif;font-weight:600;font-size:1.2rem;margin:0; } .sec-card__actions{display:flex;gap:8px;align-items:center;flex-wrap:wrap} .sec-card__empty{padding:14px 18px;margin:0} .pill{ font-family:"IBM Plex Mono",monospace;font-size:.74rem;font-weight:600; color:var(--aqua-deep);background:#E7F6F4;padding:4px 9px;border-radius:7px; } /* topic rows */ .topic-rows{list-style:none;margin:0;padding:0} .topic-row{ display:flex;align-items:center;justify-content:space-between;gap:14px; padding:12px 18px;border-bottom:1px solid var(--hair-2); } .topic-row:last-child{border-bottom:0} .topic-row__main{display:flex;align-items:center;gap:12px;min-width:0;flex-wrap:wrap} .topic-row__order{ font-family:"IBM Plex Mono",monospace;font-size:.76rem;color:var(--muted); min-width:2ch;text-align:right; } .topic-row__title{font-weight:600;color:var(--ink);text-decoration:none} .topic-row__title:hover{color:var(--aqua-deep)} .topic-row__actions{display:flex;gap:8px;flex:none} .chip{ font-family:"IBM Plex Mono",monospace;font-size:.68rem;letter-spacing:.03em; text-transform:uppercase;color:var(--muted);border:1px solid var(--hair); padding:2px 7px;border-radius:6px; } .chip--link{color:var(--aqua-deep);border-color:#B9E6E0} .empty{ background:var(--card);border:1px dashed var(--hair);border-radius:var(--radius); padding:36px;text-align:center;color:var(--muted); } /* forms */ .form-card{ background:var(--card);border:1px solid var(--hair);border-radius:var(--radius); padding:24px; } .stack{display:flex;flex-direction:column;gap:16px} .grid-2{display:grid;grid-template-columns:1fr 1fr;gap:16px} .field{display:flex;flex-direction:column;gap:6px} .field>span{font-weight:600;font-size:.86rem} .field input,.field select,.field textarea{ font-family:inherit;font-size:.94rem;color:var(--ink); padding:10px 12px;border:1px solid var(--hair);border-radius:9px;background:#fff; width:100%;transition:border-color .18s,box-shadow .18s; } .field textarea{font-family:"IBM Plex Mono",monospace;font-size:.86rem;line-height:1.5;resize:vertical} .field input:focus,.field select:focus,.field textarea:focus{ outline:none;border-color:var(--aqua);box-shadow:0 0 0 3px rgba(23,176,166,.15); } .fieldset{border:1px solid var(--hair-2);border-radius:10px;padding:16px;margin:0;display:flex;flex-direction:column;gap:14px} .fieldset legend{ font-family:"IBM Plex Mono",monospace;font-size:.72rem;letter-spacing:.1em; text-transform:uppercase;color:var(--muted);padding:0 6px; } .hint{font-size:.8rem;margin:0} .form-actions{display:flex;justify-content:flex-end;gap:10px;margin-top:4px} /* login */ .login-body{display:grid;place-items:center;min-height:100vh} .login-card{ background:var(--card);border:1px solid var(--hair);border-radius:16px; padding:36px 32px;width:min(360px,90vw);box-shadow:0 20px 50px -30px rgba(18,35,58,.5); } .login-brand{ font-family:"Bricolage Grotesque",sans-serif;font-weight:700;font-size:1.6rem; letter-spacing:-.02em; } .login-brand span{ font-family:"IBM Plex Mono",monospace;font-weight:500;font-size:.7rem; letter-spacing:.18em;text-transform:uppercase;color:var(--aqua-deep);margin-left:8px; } .login-hint{color:var(--muted);font-size:.9rem;margin:6px 0 22px} .login-card .btn{width:100%;justify-content:center;margin-top:4px} @media (max-width:620px){ .grid-2{grid-template-columns:1fr} .page-head{flex-direction:column} } /* audit log */ .filters{ display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:18px; } .filters__label{ font-family:"IBM Plex Mono",monospace;font-size:.72rem;letter-spacing:.1em; text-transform:uppercase;color:var(--muted);margin-right:4px; } .filters__sep{color:var(--hair);margin:0 2px} .filter-chip{ font-size:.82rem;text-decoration:none;color:var(--ink-soft); padding:5px 12px;border:1px solid var(--hair);border-radius:100px;background:var(--card); transition:border-color .18s,background .18s,color .18s; } .filter-chip:hover{border-color:var(--aqua)} .filter-chip.is-active{background:var(--ink);border-color:var(--ink);color:#fff} .table-wrap{ background:var(--card);border:1px solid var(--hair);border-radius:var(--radius); overflow-x:auto; } .audit-table{width:100%;border-collapse:collapse;font-size:.9rem} .audit-table th{ text-align:left;font-size:.72rem;letter-spacing:.06em;text-transform:uppercase; color:var(--muted);font-weight:600;padding:12px 14px;border-bottom:1px solid var(--hair); background:var(--hair-2);white-space:nowrap; } .audit-table td{padding:11px 14px;border-bottom:1px solid var(--hair-2);vertical-align:top} .audit-table tr:last-child td{border-bottom:0} .mono{font-family:"IBM Plex Mono",monospace;font-size:.82rem} .nowrap{white-space:nowrap} .badge{ display:inline-block;font-family:"IBM Plex Mono",monospace;font-size:.7rem; letter-spacing:.04em;text-transform:uppercase;padding:3px 9px;border-radius:6px; border:1px solid transparent; } .badge--create{background:#E7F6F4;color:#0A5A54;border-color:#B9E6E0} .badge--update{background:#FBF0E1;color:#8A5A12;border-color:#F0D9B3} .badge--delete{background:#FBEAE6;color:#9C3325;border-color:#F0C7BE} /* demo requests: per-row status + delete controls */ .inline-form{display:inline-flex;align-items:center;gap:6px;margin:0 0 6px} .mini-select{ font:inherit;font-size:.82rem;color:var(--ink);background:var(--card); border:1px solid var(--hair);border-radius:8px;padding:5px 8px; } .mini-select:focus{outline:none;border-color:var(--aqua)} .anav__count{ display:inline-block;margin-left:6px;padding:1px 7px;border-radius:100px; background:var(--aqua);color:#04201E;font-family:"IBM Plex Mono",monospace; font-size:.68rem;font-weight:600;vertical-align:middle; } .pager{display:flex;align-items:center;justify-content:center;gap:14px;margin-top:20px} .pager__info{ font-family:"IBM Plex Mono",monospace;font-size:.8rem;color:var(--muted); } .btn.is-disabled{opacity:.4;cursor:default;pointer-events:none} /* drag-to-reorder */ .drag-handle{ border:0;background:none;cursor:grab;color:var(--muted); font-size:1.1rem;line-height:1;padding:2px 4px;border-radius:6px; touch-action:none;transition:color .15s,background .15s; } .drag-handle:hover{color:var(--ink);background:var(--hair-2)} .drag-handle:active{cursor:grabbing} .sec-drag{margin-right:2px} .sortable-ghost{opacity:.45} .sortable-chosen{background:var(--hair-2)} .sec-card.sortable-ghost{outline:2px dashed var(--aqua);outline-offset:-2px} /* draft state */ .topic-row.is-draft{background:repeating-linear-gradient( -45deg,transparent,transparent 8px,rgba(232,150,58,.05) 8px,rgba(232,150,58,.05) 16px)} .topic-row.is-draft .topic-row__title{color:var(--muted)} .chip--draft{color:#8A5A12;border-color:#F0D9B3;background:#FBF0E1} /* publish checkbox on the form */ .field--check{flex-direction:row;align-items:center;gap:10px} .field--check input[type=checkbox]{width:18px;height:18px;accent-color:var(--aqua);flex:none;margin:0} .field--check>span{font-weight:600;font-size:.9rem} /* Quill rich-text editor (progressive enhancement over #body_src textarea) */ #editor-toolbar.ql-tools, #editor{display:none} /* hidden until Quill loads */ body.quill-on #editor-toolbar.ql-tools, body.quill-on #editor{display:block} body.quill-on #body_src{display:none} /* hide raw textarea once enhanced */ #editor-toolbar.ql-toolbar{ border:1px solid var(--hair);border-bottom:0;border-radius:9px 9px 0 0;background:#fff; } #editor.ql-container{ border:1px solid var(--hair);border-radius:0 0 9px 9px;background:#fff; font-family:"IBM Plex Sans",sans-serif;font-size:.98rem;min-height:180px; } #editor .ql-editor{min-height:180px} .ql-editor:focus{outline:none} #editor-toolbar.ql-toolbar .ql-stroke{stroke:var(--ink-soft)} #editor-toolbar.ql-toolbar button:hover .ql-stroke{stroke:var(--aqua-deep)} #editor-toolbar.ql-toolbar button.ql-active .ql-stroke{stroke:var(--aqua-deep)} /* Images fit the editor width; table styling is owned by quill-table-better. */ #editor .ql-editor img{max-width:100%;height:auto;border-radius:6px} #editor .ql-editor img:hover{outline:2px solid rgba(23,176,166,.35);outline-offset:2px;cursor:pointer} /* Image resize overlay (static/js/image-resize.js). Fixed-positioned over the selected image, so it never affects the editor's own layout or content. */ .jqc-imgres{ position:fixed;display:none;z-index:60;pointer-events:none; border:1.5px solid var(--aqua);border-radius:4px; } .jqc-imgres.is-active{display:block} .jqc-imgres.is-clipped{display:none} /* image scrolled out of the editor */ .jqc-imgres__handle{ position:absolute;width:11px;height:11px;background:var(--aqua); border:2px solid #fff;border-radius:50%;pointer-events:auto; box-shadow:0 1px 3px rgba(0,0,0,.25); } .jqc-imgres__handle--nw{top:-6px;left:-6px;cursor:nwse-resize} .jqc-imgres__handle--ne{top:-6px;right:-6px;cursor:nesw-resize} .jqc-imgres__handle--sw{bottom:-6px;left:-6px;cursor:nesw-resize} .jqc-imgres__handle--se{bottom:-6px;right:-6px;cursor:nwse-resize} /* top/left are set by the script (kept inside the viewport); these are just the pre-measurement defaults. */ .jqc-imgres__bar{ position:absolute;top:calc(100% + 8px);left:0;display:flex;align-items:center;gap:4px; padding:4px 6px;background:var(--ink);border-radius:8px;pointer-events:auto; box-shadow:0 6px 18px -8px rgba(0,0,0,.55);white-space:nowrap; } .jqc-imgres__btn{ font-family:"IBM Plex Mono",monospace;font-size:.72rem;letter-spacing:.04em; color:var(--paper);background:transparent;border:1px solid rgba(247,245,240,.25); border-radius:6px;padding:3px 9px;cursor:pointer; } .jqc-imgres__btn:hover{background:var(--aqua);border-color:var(--aqua);color:#04201E} .jqc-imgres__size{ font-family:"IBM Plex Mono",monospace;font-size:.7rem;color:rgba(247,245,240,.6); padding-left:4px; } /* Keep the cursor consistent and stop text selection mid-drag. */ body.jqc-imgres-dragging{cursor:ew-resize;user-select:none} /* Upload feedback for pasted/dropped images (static/js/image-upload.js). Non-blocking on purpose: an alert() mid-paste would interrupt typing. */ .jqc-toast{ position:fixed;right:20px;bottom:20px;z-index:70;max-width:min(420px,calc(100vw - 40px)); padding:11px 16px;border-radius:10px;background:var(--ink);color:var(--paper); font-size:.86rem;line-height:1.4;box-shadow:0 10px 30px -12px rgba(0,0,0,.6); opacity:0;transform:translateY(8px);pointer-events:none; transition:opacity .2s ease,transform .2s ease; } .jqc-toast.is-visible{opacity:1;transform:none} .jqc-toast--error{background:var(--danger)} .jqc-toast--busy::before{ content:"";display:inline-block;width:9px;height:9px;margin-right:8px;border-radius:50%; background:var(--aqua);animation:jqc-toast-pulse 1s ease-in-out infinite; } @keyframes jqc-toast-pulse{0%,100%{opacity:.35}50%{opacity:1}} @media (prefers-reduced-motion:reduce){ .jqc-toast{transition:none} .jqc-toast--busy::before{animation:none} }